Line data Source code
1 : //# SIMapperImageMosaic.cc: Implementation of SIMapperImageMosaic.h
2 : //# Copyright (C) 1997-2008
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This program is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU General Public License as published by the Free
7 : //# Software Foundation; either version 2 of the License, or (at your option)
8 : //# any later version.
9 : //#
10 : //# This program 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 General Public License for
13 : //# more details.
14 : //#
15 : //# You should have received a copy of the GNU General Public License along
16 : //# with this program; if not, write to the Free Software Foundation, Inc.,
17 : //# 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 : //# $Id$
27 :
28 : #include <casacore/casa/Exceptions/Error.h>
29 : #include <iostream>
30 : #include <sstream>
31 :
32 : #include <casacore/casa/Arrays/Matrix.h>
33 : #include <casacore/casa/Arrays/ArrayMath.h>
34 : #include <casacore/casa/Arrays/ArrayLogical.h>
35 :
36 : #include <casacore/casa/Logging.h>
37 : #include <casacore/casa/Logging/LogIO.h>
38 : #include <casacore/casa/Logging/LogMessage.h>
39 : #include <casacore/casa/Logging/LogSink.h>
40 : #include <casacore/casa/Logging/LogMessage.h>
41 :
42 : #include <casacore/casa/OS/DirectoryIterator.h>
43 : #include <casacore/casa/OS/File.h>
44 : #include <casacore/casa/OS/Path.h>
45 :
46 : #include <casacore/casa/OS/HostInfo.h>
47 :
48 : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
49 : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
50 :
51 : #include <synthesis/TransformMachines/BeamSkyJones.h>
52 : #include <synthesis/TransformMachines/SkyJones.h>
53 : #include <synthesis/TransformMachines/SimpleComponentFTMachine.h>
54 : #include <synthesis/TransformMachines2/SimpleComponentFTMachine.h>
55 : #include <synthesis/TransformMachines/SimpCompGridMachine.h>
56 :
57 : #include <synthesis/ImagerObjects/SIMapperImageMosaic.h>
58 :
59 :
60 : #include <sys/types.h>
61 : #include <unistd.h>
62 : using namespace std;
63 :
64 : using namespace casacore;
65 : namespace casa { //# NAMESPACE CASA - BEGIN
66 :
67 0 : SIMapperImageMosaic::SIMapperImageMosaic( CountedPtr<SIImageStore>& imagestore,
68 : CountedPtr<FTMachine>& ftm,
69 0 : CountedPtr<FTMachine>& iftm)
70 : // CountedPtr<VPSkyJones>& vp)
71 0 : : SIMapper( imagestore, ftm, iftm )
72 : // vb_p (vi::VisBuffer2::factory (vi::VbRekeyable))
73 : {
74 0 : LogIO os( LogOrigin("SIMapperImageMosaic","Constructor",WHERE) );
75 :
76 : /*
77 : if( !vp.null() ) {
78 : ejgrid_p=vp;
79 : ejdegrid_p=vp;
80 : }
81 : else {
82 : ejgrid_p=NULL;
83 : ejdegrid_p=NULL;
84 : }
85 : */
86 :
87 0 : firstaccess_p = true;
88 :
89 0 : }
90 0 : SIMapperImageMosaic::SIMapperImageMosaic( CountedPtr<SIImageStore>& imagestore,
91 : CountedPtr<refim::FTMachine>& ftm,
92 0 : CountedPtr<refim::FTMachine>& iftm)
93 : // CountedPtr<VPSkyJones>& vp)
94 0 : : SIMapper( imagestore, ftm, iftm ), vb_p (vi::VisBuffer2::factory (vi::VbRekeyable))
95 : {
96 0 : LogIO os( LogOrigin("SIMapperImageMosaic","Constructor",WHERE) );
97 :
98 : /*
99 : if( !vp.null() ) {
100 : ejgrid_p=vp;
101 : ejdegrid_p=vp;
102 : }
103 : else {
104 : ejgrid_p=NULL;
105 : ejdegrid_p=NULL;
106 : }
107 : */
108 :
109 0 : firstaccess_p = true;
110 :
111 0 : }
112 0 : SIMapperImageMosaic::SIMapperImageMosaic(const ComponentList& cl,
113 0 : String& whichMachine)
114 : // CountedPtr<VPSkyJones>& vp)
115 0 : : SIMapper(cl, whichMachine ), vb_p (vi::VisBuffer2::factory (vi::VbRekeyable))
116 : {
117 :
118 : /*
119 : if( !vp.null() ) {
120 : ejgrid_p=vp;
121 : ejdegrid_p=vp;
122 : }
123 : else {
124 : ejgrid_p=NULL;
125 : ejdegrid_p=NULL;
126 : }
127 : */
128 0 : clCorrupted_p=cl;
129 :
130 0 : firstaccess_p = true;
131 :
132 0 : }
133 :
134 0 : SIMapperImageMosaic::~SIMapperImageMosaic()
135 : {
136 0 : }
137 :
138 : // #############################################
139 : // #############################################
140 : // ####### Gridding / De-gridding functions ###########
141 : // #############################################
142 : // #############################################
143 0 : void SIMapperImageMosaic::initializeGrid(vi::VisBuffer2& vb, Bool dopsf, Bool firstaccess)
144 : {
145 :
146 0 : LogIO os( LogOrigin("SIMapperImageMosaic","initializeGrid",WHERE) );
147 0 : if(!useViVb2_p)
148 0 : throw(AipsError("Programmer Error: using vi2 mode with vi1 constructor"));
149 : //Componentlist FTM has nothing to do
150 0 : if(ift2_p.null())
151 0 : return;
152 :
153 0 : ift2_p->initializeToSkyNew( dopsf, vb, itsImages);
154 : /*
155 : Bool dirDep= ift2_p->isSkyJonesSet(); // (!ejgrid_p.null());
156 : dirDep= dirDep || ((ift2_p->name()) == "MosaicFT");
157 : ovb_p.assign(vb, false);
158 : ovb_p.updateCoordInfo(&vb, dirDep);
159 : */
160 0 : vb_p->copy(vb, false);
161 0 : firstaccess_p = firstaccess;
162 :
163 0 : }
164 :
165 :
166 0 : void SIMapperImageMosaic::initializeGrid(VisBuffer& vb, Bool dopsf, Bool firstaccess)
167 : {
168 :
169 0 : LogIO os( LogOrigin("SIMapperImageMosaic","initializeGrid",WHERE) );
170 0 : if(useViVb2_p)
171 0 : throw(AipsError("Programmer Error: using vi1 mode with vi2 constructor"));
172 : //Componentlist FTM has nothing to do
173 0 : if(ift_p.null())
174 0 : return;
175 :
176 0 : ift_p->initializeToSkyNew( dopsf, vb, itsImages);
177 :
178 0 : Bool dirDep= ift_p->isSkyJonesSet(); // (!ejgrid_p.null());
179 0 : dirDep= dirDep || ((ift_p->name()) == "MosaicFT");
180 0 : ovb_p.assign(vb, false);
181 0 : ovb_p.updateCoordInfo(&vb, dirDep);
182 :
183 0 : firstaccess_p = firstaccess;
184 :
185 0 : }
186 :
187 :
188 0 : void SIMapperImageMosaic::grid(vi::VisBuffer2& vb, Bool dopsf, refim::FTMachine::Type col)
189 : {
190 0 : LogIO os( LogOrigin("SIMapperImageMosaic","grid",WHERE) );
191 0 : if(!useViVb2_p)
192 0 : throw(AipsError("Programmer Error: using vi2 mode with vi1 constructor"));
193 : //Componentlist FTM has no gridding to do
194 0 : if(ift2_p.null())
195 0 : return;
196 :
197 0 : Int nRow=vb.nRows();
198 0 : Bool internalChanges=false; // Does this VB change inside itself?
199 0 : Bool firstOneChanges=false; // Has this VB changed from the previous one?
200 0 : if((ift2_p->name() != "MosaicFT") && (ift2_p->name() != "PBWProjectFT") &&
201 0 : (ift2_p->name() != "AWProjectFT") && (ift2_p->name() != "AWProjectWBFT")) {
202 0 : ift2_p->changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
203 : }
204 : //First ft machine change should be indicative
205 : //anyways right now we are allowing only 1 ftmachine for GridBoth
206 0 : Bool IFTChanged=ift2_p->changed(vb);
207 :
208 : // cout << "gridCoreMos : internalChanges : " << internalChanges << " firstchange : " << firstOneChanges << endl;
209 :
210 0 : if(internalChanges) {
211 : // Yes there are changes: go row by row.
212 0 : for (Int row=0; row<nRow; row++)
213 : {
214 : //// if(IFTChanged||ejgrid_p->changed(vb,row))
215 0 : if(IFTChanged|| ift2_p->isSkyJonesChanged(vb,row))
216 : {
217 : // Need to apply the SkyJones from the previous row
218 : // and finish off before starting with this row
219 :
220 0 : finalizeGrid( *vb_p, dopsf );
221 0 : initializeGrid( vb, dopsf );
222 :
223 : }
224 0 : ift2_p->put(vb, row, dopsf, col);
225 : //gridCore( vb, dopsf, col, ftm, row );
226 : }
227 0 : } else if (IFTChanged || firstOneChanges) {
228 : //IMPORTANT:We need to finalize here by checking that we are not at the begining of the iteration
229 0 : if( !firstaccess_p )
230 : {
231 0 : finalizeGrid( *vb_p, dopsf );
232 0 : firstaccess_p=false;
233 : }
234 0 : initializeGrid( vb, dopsf );
235 0 : ift2_p->put(vb, -1, dopsf, col);
236 : } else {
237 0 : ift2_p->put(vb, -1, dopsf, col);
238 : }
239 :
240 0 : }
241 :
242 :
243 : /////////////////OLD vi/vb version
244 0 : void SIMapperImageMosaic::grid(VisBuffer& vb, Bool dopsf, FTMachine::Type col)
245 : {
246 0 : LogIO os( LogOrigin("SIMapperImageMosaic","grid",WHERE) );
247 0 : if(useViVb2_p)
248 0 : throw(AipsError("Programmer Error: using vi1 mode with vi2 constructor"));
249 : //Componentlist FTM has no gridding to do
250 0 : if(ift_p.null())
251 0 : return;
252 :
253 0 : Int nRow=vb.nRow();
254 0 : Bool internalChanges=false; // Does this VB change inside itself?
255 0 : Bool firstOneChanges=false; // Has this VB changed from the previous one?
256 0 : if((ift_p->name() != "MosaicFT") && (ift_p->name() != "PBWProjectFT") &&
257 0 : (ift_p->name() != "AWProjectFT") && (ift_p->name() != "AWProjectWBFT")) {
258 0 : ift_p->changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
259 : }
260 : //First ft machine change should be indicative
261 : //anyways right now we are allowing only 1 ftmachine for GridBoth
262 0 : Bool IFTChanged=ift_p->changed(vb);
263 :
264 : // cout << "gridCoreMos : internalChanges : " << internalChanges << " firstchange : " << firstOneChanges << endl;
265 :
266 0 : if(internalChanges) {
267 : // Yes there are changes: go row by row.
268 0 : for (Int row=0; row<nRow; row++)
269 : {
270 : //// if(IFTChanged||ejgrid_p->changed(vb,row))
271 0 : if(IFTChanged|| ift_p->isSkyJonesChanged(vb,row))
272 : {
273 : // Need to apply the SkyJones from the previous row
274 : // and finish off before starting with this row
275 :
276 0 : finalizeGrid( ovb_p, dopsf );
277 0 : initializeGrid( vb, dopsf );
278 :
279 : }
280 0 : ift_p->put(vb, row, dopsf, col);
281 : //gridCore( vb, dopsf, col, ftm, row );
282 : }
283 0 : } else if (IFTChanged || firstOneChanges) {
284 : //IMPORTANT:We need to finalize here by checking that we are not at the begining of the iteration
285 0 : if( !firstaccess_p )
286 : {
287 0 : finalizeGrid( ovb_p, dopsf );
288 0 : firstaccess_p=false;
289 : }
290 0 : initializeGrid( vb, dopsf );
291 0 : ift_p->put(vb, -1, dopsf, col);
292 : } else {
293 0 : ift_p->put(vb, -1, dopsf, col);
294 : }
295 :
296 0 : }
297 :
298 0 : void SIMapperImageMosaic::finalizeGrid(vi::VisBuffer2& vb, Bool dopsf)
299 : {
300 0 : LogIO os( LogOrigin("SIMapperImageMosaic","finalizeGrid",WHERE) );
301 0 : if(!useViVb2_p)
302 0 : throw(AipsError("Programmer Error: using vi2 mode with vi1 constructor"));
303 :
304 0 : if(ift2_p.null())
305 0 : return;
306 :
307 0 : ift2_p->finalizeToSkyNew( dopsf, vb, itsImages );
308 0 : }
309 :
310 : //////////////OLD VI/VB version
311 0 : void SIMapperImageMosaic::finalizeGrid(VisBuffer& vb, Bool dopsf)
312 : {
313 0 : LogIO os( LogOrigin("SIMapperImageMosaic","finalizeGrid",WHERE) );
314 0 : if(useViVb2_p)
315 0 : throw(AipsError("Programmer Error: using vi1 mode with vi2 constructor"));
316 :
317 0 : if(ift_p.null())
318 0 : return;
319 :
320 0 : ift_p->finalizeToSkyNew( dopsf, vb, itsImages );
321 0 : }
322 :
323 0 : void SIMapperImageMosaic::initializeDegrid(vi::VisBuffer2& vb, const Int /*row*/)
324 : {
325 0 : LogIO os( LogOrigin("SIMapperImageMosaic", "initializeDegrid",WHERE) );
326 0 : if(!useViVb2_p)
327 0 : throw(AipsError("Programmer Error: using vi2 mode with vi1 constructor"));
328 0 : if(ft2_p.null() && cft2_p.null())
329 0 : return;
330 :
331 0 : ft2_p->initializeToVisNew(vb, itsImages);
332 :
333 : /// Add a call here, to do corrupt cl_p and create clCorrupted_p;
334 : /// This should happen inside the SimpleComponentMachine, which will be init'd with the SkyJones.
335 : /// For now, it's just clCorrupted_p = cl_p.
336 :
337 : /*
338 : if(!cftm.null()) {
339 : clCorrupted_p=ComponentList();
340 : for (uInt k=0; k < cl.nelements(); ++k){
341 : SkyComponent comp=cl.component(k).copy();
342 : if(vb.polFrame()==MSIter::Linear) {
343 : if(comp.flux().pol()==ComponentType::STOKES) {
344 : comp.flux().convertPol(ComponentType::LINEAR);
345 : }
346 : }
347 : else {
348 : if(comp.flux().pol()==ComponentType::STOKES) {
349 : comp.flux().convertPol(ComponentType::CIRCULAR);
350 : }
351 : }
352 : ////We might have to deal with the right row here if the visbuffer is has changed internally
353 : ejdegrid_p->apply(comp, comp, vb,row, true);
354 : clCorrupted_p.add(comp);
355 : }
356 : }
357 : */
358 :
359 0 : }
360 :
361 : //////////////////OLD vi/vb version
362 0 : void SIMapperImageMosaic::initializeDegrid(VisBuffer& vb, const Int /*row*/)
363 : {
364 0 : LogIO os( LogOrigin("SIMapperImageMosaic", "initializeDegrid",WHERE) );
365 0 : if(useViVb2_p)
366 0 : throw(AipsError("Programmer Error: using vi1 mode with vi2 constructor"));
367 0 : if(ft_p.null() && cft_p.null())
368 0 : return;
369 :
370 0 : ft_p->initializeToVisNew(vb, itsImages);
371 :
372 : /// Add a call here, to do corrupt cl_p and create clCorrupted_p;
373 : /// This should happen inside the SimpleComponentMachine, which will be init'd with the SkyJones.
374 : /// For now, it's just clCorrupted_p = cl_p.
375 :
376 : /*
377 : if(!cftm.null()) {
378 : clCorrupted_p=ComponentList();
379 : for (uInt k=0; k < cl.nelements(); ++k){
380 : SkyComponent comp=cl.component(k).copy();
381 : if(vb.polFrame()==MSIter::Linear) {
382 : if(comp.flux().pol()==ComponentType::STOKES) {
383 : comp.flux().convertPol(ComponentType::LINEAR);
384 : }
385 : }
386 : else {
387 : if(comp.flux().pol()==ComponentType::STOKES) {
388 : comp.flux().convertPol(ComponentType::CIRCULAR);
389 : }
390 : }
391 : ////We might have to deal with the right row here if the visbuffer is has changed internally
392 : ejdegrid_p->apply(comp, comp, vb,row, true);
393 : clCorrupted_p.add(comp);
394 : }
395 : }
396 : */
397 :
398 0 : }
399 :
400 0 : void SIMapperImageMosaic::degrid(vi::VisBuffer2& vb)
401 : {
402 0 : LogIO os( LogOrigin("SIMapperImageMosaic","degrid",WHERE) );
403 0 : if(!useViVb2_p)
404 0 : throw(AipsError("Programmer Error: using vi2 mode with vi1 constructor"));
405 : ///This should not be called even but heck let's ignore
406 0 : if(ft2_p.null() and cft2_p.null())
407 0 : return;
408 :
409 0 : Cube<Complex> origCube;
410 0 : origCube.assign(vb.visCubeModel());
411 :
412 0 : Int nRow=vb.nRows();
413 0 : Bool internalChanges=false; // Does this VB change inside itself?
414 0 : Bool firstOneChanges=false; // Has this VB changed from the previous one?
415 :
416 0 : if((!ft2_p.null() && (ft2_p->name() != "MosaicFT") && (ft2_p->name() != "PBWProjectFT") &&
417 0 : (ft2_p->name() != "AWProjectFT") && (ft2_p->name() != "AWProjectWBFT")) || (!cft2_p.null())) {
418 0 : ft2_p->changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
419 : }
420 : //anyways right now we are allowing only 1 ftmachine for GridBoth
421 0 : Bool FTChanged=ft2_p->changed(vb);
422 :
423 0 : if(internalChanges)
424 : {
425 : // Yes there are changes within this buffer: go row by row.
426 : // This will automatically catch a change in the FTMachine so
427 : // we don't have to check for that.
428 0 : for (Int row=0; row<nRow; row++)
429 : {
430 : //// if(FTChanged||ejdegrid_p->changed(vb,row))
431 0 : if(FTChanged|| ft2_p->isSkyJonesChanged(vb,row) )
432 : {
433 : // Need to apply the SkyJones from the previous row
434 : // and finish off before starting with this row
435 0 : finalizeDegrid();
436 0 : initializeDegrid(vb,row);
437 : }
438 0 : ft2_p.null() ? cft2_p->get(vb, clCorrupted_p, row) : ft2_p->get(vb, row);
439 :
440 : }
441 :
442 : }
443 0 : else if (FTChanged||firstOneChanges) {
444 : // This buffer has changed wrt the previous buffer, but
445 : // this buffer has no changes within it. Again we don't need to
446 : // check for the FTMachine changing.
447 0 : finalizeDegrid();
448 0 : initializeDegrid(vb, 0);
449 :
450 0 : ft2_p.null() ? cft2_p->get(vb, clCorrupted_p) : ft2_p->get(vb);
451 : }
452 : else {
453 0 : ft2_p.null() ? cft2_p->get(vb, clCorrupted_p) : ft2_p->get(vb);
454 : }
455 0 : origCube+=vb.visCubeModel();
456 0 : vb.setVisCubeModel(origCube);
457 :
458 0 : }
459 :
460 : ////////////////////Old vi/Vb version
461 :
462 0 : void SIMapperImageMosaic::degrid(VisBuffer& vb)
463 : {
464 0 : LogIO os( LogOrigin("SIMapperImageMosaic","degrid",WHERE) );
465 0 : if(useViVb2_p)
466 0 : throw(AipsError("Programmer Error: using vi1 mode with vi2 constructor"));
467 : ///This should not be called even but heck let's ignore
468 0 : if(ft_p.null() and cft_p.null())
469 0 : return;
470 :
471 0 : Cube<Complex> origCube;
472 0 : origCube.assign(vb.modelVisCube());
473 :
474 0 : Int nRow=vb.nRow();
475 0 : Bool internalChanges=false; // Does this VB change inside itself?
476 0 : Bool firstOneChanges=false; // Has this VB changed from the previous one?
477 :
478 0 : if((!ft_p.null() && (ft_p->name() != "MosaicFT") && (ft_p->name() != "PBWProjectFT") &&
479 0 : (ft_p->name() != "AWProjectFT") && (ft_p->name() != "AWProjectWBFT")) || (!cft_p.null())) {
480 0 : ft_p->changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
481 : }
482 : //anyways right now we are allowing only 1 ftmachine for GridBoth
483 0 : Bool FTChanged=ft_p->changed(vb);
484 :
485 0 : if(internalChanges)
486 : {
487 : // Yes there are changes within this buffer: go row by row.
488 : // This will automatically catch a change in the FTMachine so
489 : // we don't have to check for that.
490 0 : for (Int row=0; row<nRow; row++)
491 : {
492 : //// if(FTChanged||ejdegrid_p->changed(vb,row))
493 0 : if(FTChanged|| ft_p->isSkyJonesChanged(vb,row) )
494 : {
495 : // Need to apply the SkyJones from the previous row
496 : // and finish off before starting with this row
497 0 : finalizeDegrid();
498 0 : initializeDegrid(vb,row);
499 : }
500 0 : ft_p.null() ? cft_p->get(vb, clCorrupted_p, row) : ft_p->get(vb, row);
501 :
502 : }
503 :
504 : }
505 0 : else if (FTChanged||firstOneChanges) {
506 : // This buffer has changed wrt the previous buffer, but
507 : // this buffer has no changes within it. Again we don't need to
508 : // check for the FTMachine changing.
509 0 : finalizeDegrid();
510 0 : initializeDegrid(vb, 0);
511 :
512 0 : ft_p.null() ? cft_p->get(vb, clCorrupted_p) : ft_p->get(vb);
513 : }
514 : else {
515 0 : ft_p.null() ? cft_p->get(vb, clCorrupted_p) : ft_p->get(vb);
516 : }
517 :
518 0 : vb.modelVisCube()+=origCube;
519 :
520 0 : }
521 :
522 :
523 : /*
524 : Bool SIMapperImageMosaic::changedSkyJonesLogic(const vi::VisBuffer2& vb, Bool& firstRow, Bool& internalRow, const Bool grid){
525 : firstRow=false;
526 : internalRow=false;
527 : CountedPtr<VPSkyJones> ej= grid ? ejgrid_p : ejdegrid_p;
528 : if(ej.null())
529 : return false;
530 : if(ej->changed(vi::VisBuffer2Adapter(&vb),0))
531 : firstRow=true;
532 : Int row2temp=0;
533 : if(ej->changedBuffer(vi::VisBuffer2Adapter(&vb),0,row2temp)) {
534 : internalRow=true;
535 : }
536 : return (firstRow || internalRow) ;
537 : }
538 : ////////////Old VB version
539 : Bool SIMapperImageMosaic::changedSkyJonesLogic(const VisBuffer& vb, Bool& firstRow, Bool& internalRow, const Bool grid){
540 : firstRow=false;
541 : internalRow=false;
542 : CountedPtr<VPSkyJones> ej= grid ? ejgrid_p : ejdegrid_p;
543 : if(ej.null())
544 : return false;
545 : if(ej->changed(vb,0))
546 : firstRow=true;
547 : Int row2temp=0;
548 : if(ej->changedBuffer(vb,0,row2temp)) {
549 : internalRow=true;
550 : }
551 : return (firstRow || internalRow) ;
552 : }
553 : */
554 :
555 :
556 : } //# NAMESPACE CASA - END
557 :
|