diff --git a/Appl/CEP/CS1/CS1_pp_lib/scripts/CS1_Offline_pipeline_control.py b/Appl/CEP/CS1/CS1_pp_lib/scripts/CS1_Offline_pipeline_control.py new file mode 100644 index 0000000000000000000000000000000000000000..6f630b8c56d41cafecc3fec32543d01c90a65d17 --- /dev/null +++ b/Appl/CEP/CS1/CS1_pp_lib/scripts/CS1_Offline_pipeline_control.py @@ -0,0 +1,127 @@ +from optparse import OptionParser +from LOFAR_Parset import Parset +import sys, os, time + +parser = OptionParser(usage='%prog [options] -m<Obs name>') +parser.add_option("-o", "--obs", dest="obs", default="", + help="Observation name") + +options, args = parser.parse_args() + +Observation = options.obs + +##settings +node_dir = '/local/renting' +run_id = 'test01' +nodes = [('lioff001','SB0.MS'),('lioff002','SB1.MS'),('lioff003','SB2.MS'), +('lioff004','SB3.MS'),('lioff005','SB4.MS'),('lioff006','SB5.MS'), +('lioff007','SB6.MS'),('lioff008','SB7.MS'),('lioff009','SB8.MS'), +('lioff010','SB9.MS'),('lioff011','SB10.MS'),('lioff012','SB11.MS'), +('lioff013','SB12.MS'),('lioff014','SB13.MS'),('lioff015','SB14.MS'), +('lioff016','SB15.MS'),('lioff017','SB16.MS'),('lioff018','SB17.MS') +] + + +if Observation == "": + print "No Observation set given, exiting" + sys.exit(1) +else: + if not os.path.exists(Observation): + print "Observation does not exist, exiting" + sys.exit(2) + +try: + os.environ['AIPSPATH'] +except: + print "AIPSPATH not set, exiting" + sys.exit(3) + +try: + os.environ['SSH_AGENT_PID'] +except: + print "SSH-AGENT not active, exiting" + sys.exit(3) + +pidlist = [] + +def spawn(host, MS): + try: + pid = os.fork() + except OSError, e: + print 'Unable to fork:' + str(e) + os._exit(1) + if pid == 0: ## the new client + ##Copy node script so we are sure we are running the right version + os.system('scp CS1_Offline_pipeline_node.py ' + host + ':' + node_dir + + '/CS1_Offline_pipeline_node.py') + ##Copy the subband MS + os.system('scp -r ' + Observation + '/' + MS + + ' ' + host + ':' + node_dir + '/' + MS) + ##Run the node script on every node + os.system('ssh -t ' + host + + ' "setenv PYTHONPATH /app/LOFAR/stable;' + + 'source /app/scripts/doUnstableAIPS++;cd '+node_dir + ';python ' + node_dir + + '/CS1_Offline_pipeline_node.py -m' + + node_dir + '/' + MS + + ' >> ' + run_id + '.log"') + os._exit(0) + else: ## parent process + pidlist.append(pid) + +for node in nodes: + spawn(node[0], node[1]) + +time.sleep(10) ## wait for childs to spawn +for p in pidlist: ## wait for the clients to finish + (pid, status) = os.waitpid(p, 0) + print 'result: ' + str(nodes[pidlist.index(pid)]) + ' ' + str(pid) + ' ' + str(status) + +MSlist = [] +for node in nodes: + ## get the squashed measurementsets back + os.system('scp -r ' + node[0] + ':' + node_dir + '/s' + node[1] + ' .') + MSlist.append('s' + node[1]) + +MS = 'result.MS' + +Combiner_parset = Parset() +Combiner_parset['inms'] = MSlist +Combiner_parset['out'] = MS +Combiner_parset.writeToFile("CS1_SPWCombine.parset") +fd = open("CS1_SPWComine.debug", 'w') +fd.write("Global 20\n") +fd.write("Everything 20\n") +fd.close() + +## Unsure if these are usefull imager parameters, probably onlt around 60 MHz +Imager_parset = Parset() +Imager_parset['ms'] = MS +Imager_parset['compress'] = "False" +Imager_parset['datamode'] = "channel" +Imager_parset['imagemode'] = "mfs" +Imager_parset['spwid'] = [0,1] +Imager_parset['nchan'] = 256 +Imager_parset['start'] = 0 +Imager_parset['step'] = 1 +Imager_parset['nx'] = 512 +Imager_parset['ny'] = 512 +Imager_parset['cellx'] = 750 +Imager_parset['celly'] = 750 +Imager_parset['stokes'] = "I" +Imager_parset['weighttype'] = "natural" +Imager_parset['weightnpixels'] = 1024 +Imager_parset['tile'] = 32 +Imager_parset['padding'] = 1.0 +Imager_parset['gridfunction'] = "SF" +Imager_parset['imagetype'] = "observed" +Imager_parset['imagename'] = "observed.image" +Flagger_parset.writeToFile("CS1_Imager.parset") +fd = open("CS1_Imager.debug", 'w') +fd.write("Global 20\n") +fd.write("Everything 20\n") +fd.close() + +## some processing on the final MS +os.system("/app/LOFAR/stable/CS1_SPWCombine") +os.system("glish -l /app/LOFAR/stable/flag_auto.g " + MS) +#os.system("/app/LOFAR/stable/CS1_Imager") diff --git a/Appl/CEP/CS1/CS1_pp_lib/scripts/CS1_Offline_pipeline_node.py b/Appl/CEP/CS1/CS1_pp_lib/scripts/CS1_Offline_pipeline_node.py new file mode 100644 index 0000000000000000000000000000000000000000..529a3a960c992a57e7604dd0510803ec24a6f49e --- /dev/null +++ b/Appl/CEP/CS1/CS1_pp_lib/scripts/CS1_Offline_pipeline_node.py @@ -0,0 +1,65 @@ +from optparse import OptionParser +from LOFAR_Parset import Parset +import sys, os + +parser = OptionParser(usage='%prog [options] -m<MS name>') +parser.add_option("-m", "--msin", dest="msin", default="", + help="Measurementset name") + +options, args = parser.parse_args() + +MS = options.msin + +if MS == "": + print "No Measurement set given, exiting" + sys.exit(1) +else: + if not os.path.exists(MS): + print "MS does not exist, exiting" + sys.exit(2) + +try: + os.environ['AIPSPATH'] +except: + print "AIPSPATH not set, exiting" + sys.exit(3) + +Bandpass_parset = Parset() +Bandpass_parset['ms'] = MS +Bandpass_parset['fixed'] = 5 +Bandpass_parset['window'] = 1 +Bandpass_parset.writeToFile("CS1_BandpassCorrector.parset") +fd = open("CS1_BandpassCorrector.debug", 'w') +fd.write("Global 20\n") +fd.write("Everything 20\n") +fd.close() + +Flagger_parset = Parset() +Flagger_parset['ms'] = MS +Flagger_parset['existing'] = False +Flagger_parset['threshold']= 1.1 +Flagger_parset.writeToFile("CS1_frequencyFlagger.parset") +fd = open("CS1_FrequencyFlagger.debug", 'w') +fd.write("Global 20\n") +fd.write("Everything 20\n") +fd.close() + +Squasher_parset = Parset() +(head, tail) = os.path.split(MS) +Squasher_parset['inms'] = MS +Squasher_parset['outms'] = head + "/s" + tail +Squasher_parset['start'] = 0 +Squasher_parset['step'] = 64 +Squasher_parset['nchan'] = 256 +Squasher_parset['threshold'] = 0 +Squasher_parset['useflags'] = True +Squasher_parset['allcolumns'] = True +Squasher_parset.writeToFile("CS1_DataSquasher.parset") +fd = open("CS1_DataSquasher.debug", 'w') +fd.write("Global 20\n") +fd.write("Everything 20\n") +fd.close() + +os.system("/app/LOFAR/stable/CS1_BandpassCorrector") +os.system("/app/LOFAR/stable/CS1_FrequencyFlagger") +os.system("/app/LOFAR/stable/CS1_DataSquasher") diff --git a/Appl/CEP/CS1/CS1_pp_lib/src/FlaggerStatistics.cc b/Appl/CEP/CS1/CS1_pp_lib/src/FlaggerStatistics.cc new file mode 100644 index 0000000000000000000000000000000000000000..a32d7e89fb8bfa37c5b1355d1d069e5f6eebf6cf --- /dev/null +++ b/Appl/CEP/CS1/CS1_pp_lib/src/FlaggerStatistics.cc @@ -0,0 +1,565 @@ +/*************************************************************************** + * Copyright (C) 2006 by ASTRON, Adriaan Renting * + * renting@astron.nl * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include <tables/Tables.h> +#include <tables/Tables/TableIter.h> +#include "ComplexMedianFlagger.h" +#include <casa/Quanta/MVEpoch.h> + +using namespace WSRT; //should be nfra ? +using namespace casa; + +enum CorrelationTypes {None=0,I=1,Q=2,U=3,V=4,RR=5,RL=6,LR=7,LL=8,XX=9,XY=10,YX=11,YY=12}; //found somewhere in AIPS++, don't remember where + +//===============>>> itoa <<<=============== +//ANSI C++ doesn't seem to have a decent function for this, or I'm not aware of it. Need to rename it to IntToStr(), to avoid confusion +std::string itoa(int value, int base=10) +{ // found on http://www.jb.man.ac.uk/~slowe/cpp/itoa.html + //maybe copyright Robert Jan Schaper, Ray-Yuan Sheu, Rodrigo de Salvo Braz, Wes Garland and John Maloney + enum { kMaxDigits = 35 }; + std::string buf; + buf.reserve( kMaxDigits ); // Pre-allocate enough space. + // check that the base if valid + if (base < 2 || base > 16) return buf; + int quotient = value; + // Translating number to string with base: + do { + buf += "0123456789abcdef"[ std::abs( quotient % base ) ]; + quotient /= base; + } while ( quotient ); + // Append the negative sign for base 10 + if ( value < 0 && base == 10) buf += '-'; + std::reverse( buf.begin(), buf.end() ); + return buf; +} + +//===============>>> ComplexMedianFlagger::ComplexMedianFlagger <<<=============== +/* initialize some meta data and get the datastorage the right size. */ +ComplexMedianFlagger::ComplexMedianFlagger(MS_File* InputMSfile, + int InputWindowSize, + bool UseOnlyXpolarizations, + double InputMinThreshold, + double InputMaxThreshold) +{ + MSfile = InputMSfile; + WindowSize = InputWindowSize; + MinThreshold = InputMinThreshold; + MaxThreshold = InputMaxThreshold; + NumAntennae = (*MSfile).itsNumAntennae; + NumPairs = (*MSfile).itsNumPairs; + NumBands = (*MSfile).itsNumBands; + NumChannels = (*MSfile).itsNumChannels; + NumPolarizations = (*MSfile).itsNumPolarizations; + NoiseLevel = (*MSfile).itsNoiseLevel; + NumTimeslots = (*MSfile).itsNumTimeslots; + AntennaNames = (*MSfile).itsAntennaNames; + + PairsIndex.resize(NumPairs); + Statistics = Cube<int>(NumBands, NumAntennae, NumAntennae, 0); + PolarizationsToCheck.resize(NumPolarizations); + DeterminePolarizationsToCheck(UseOnlyXpolarizations); + + TimeslotData.resize(NumPairs*NumBands); + for (int i = 0; i < NumPairs*NumBands; i++) + { TimeslotData[i].resize(NumPolarizations, NumChannels, WindowSize); + } + + int index = 0; + for (int i = 0; i < NumAntennae; i++) + { for(int j = i; j < NumAntennae; j++) + { PairsIndex[index] = pairii(i, j); + BaselineIndex[pairii(i, j)] = index++; + } + } + ComputeBaselineLengths(); +} + +//===============>>> ComplexMedianFlagger::~ComplexMedianFlagger <<<=============== + +ComplexMedianFlagger::~ComplexMedianFlagger() +{ +} + +//===============>>> ComplexMedianFlagger::DetermineCorrelationsToCheck <<<=============== +/* create a list of polarizations we want to check, maybe we only want to to XY, YX */ +void ComplexMedianFlagger::DeterminePolarizationsToCheck(bool UseOnlyXpolarizations) +{ + if (UseOnlyXpolarizations) + { + bool noCorrError = true; + for (int i = 0; i < NumPolarizations; i++) + { + switch((*MSfile).itsPolarizations[i]) + { + case None: + case I: + case RR: + case LL: + case XX: + case YY: + if (UseOnlyXpolarizations) + PolarizationsToCheck[i] = false; + break; + case Q: + case U: + case V: + case RL: + case LR: + case XY: + case YX: + noCorrError = false; + if (UseOnlyXpolarizations) + PolarizationsToCheck[i] = true; + break; + } + } + if (noCorrError) + { + cout << "There are no crosspolarizations to flag!"; + exit(1); + } + } + else + { + for (int i = 0; i < NumPolarizations; i++) + { PolarizationsToCheck[i] = true; + } + } +} + +//===============>>> ComplexMedianFlagger::ComputeBaselineLengths <<<=============== +/* compute baseline lengths, and determine the longest one.*/ +void ComplexMedianFlagger::ComputeBaselineLengths() +{ + MaxBaselineLength = 0.0; + BaselineLengths.resize(NumPairs); + //Antenna positions + MSAntenna antenna = (*MSfile).antenna(); + ROArrayColumn<Double> position(antenna, "POSITION"); + for (int i = 0; i < NumAntennae; i++ ) + { + for (int j = i; j < NumAntennae; j++) + { + Vector<Double> p(position(i) - position(j)); + double temp = sqrt(p(0)*p(0) + p(1)*p(1) + p(2)*p(2)); + BaselineLengths[BaselineIndex[pairii(i, j)]] = temp; + if (temp > MaxBaselineLength && temp < 3000000) //radius of the Earth in meters? WSRT sometimes has fake telescopes at 3854243 + { MaxBaselineLength = temp; // non-existent antenna's can have position (0,0,0) + } + } + } +} + +//===============>>> ComplexMedianFlagger::FlagDataOrBaselines <<<=============== +/*This function outputs the gathered statistics.*/ +void ComplexMedianFlagger::ProcessStatistics() +{ + vector<int> bands(NumBands); + vector<int> antennae(NumAntennae); + unsigned int namelength = 6; + for(int i = 0; i < NumAntennae; i++) + { + if (namelength < AntennaNames[i].size()) + { namelength = AntennaNames[i].size(); + } + } + for (int i = 0; i < NumBands; i++) + { + cout << "Band: " << i+1 << endl; + cout << string(namelength+1,' '); + for(int j = 0; j < NumAntennae; j++) + { + string out = AntennaNames[j]; + out.resize(namelength+1,' '); + cout << out; + } + cout << endl; + for(int j = 0; j < NumAntennae; j++) + { + string out = AntennaNames[j]; + out.resize(namelength+1,' '); + cout << out; + for(int k = 0; k < NumAntennae; k++) + { + if (k < j) //We print a complete array, but we have inspected only those where k >= j + { + int val = 100 * Statistics(i,k,j) / (NumChannels * NumTimeslots * NumPolarizations); + bands[i] += val; + antennae[j] += val; + antennae[k] += val; + string out = itoa(val) + "%"; + out.resize(namelength+1,' '); + cout << out; + } + else + { + int val = 100 * Statistics(i,j,k) / (NumChannels * NumTimeslots * NumPolarizations); + bands[i] += val; + antennae[j] += val; + antennae[k] += val; + string out = itoa(val) + "%"; + out.resize(namelength+1,' '); + cout << out; + } + /*{ cout << rms << "Faulty baseline detected: Antenna " << j+1 + << ":" << k+1 << " SpectralWindow: "<< i+1 << endl; + } + }*/ + } + cout << endl; + } + } + cout << "Bands (flagged %): "; + for (int i = 0; i < NumBands; i++) + { + string out = string("IVC") + itoa(i); + out.resize(namelength+1,' '); + cout << out; + } + cout << endl << " "; + for (int i = 0; i < NumBands; i++) + { + string out = itoa(bands[i] / (NumAntennae*NumAntennae)) + "%"; + out.resize(namelength+1,' '); + cout << out; + } + cout << endl << "Antennae (flagged %): " ; + for(int j = 0; j < NumAntennae; j++) + { + string out = AntennaNames[j]; + out.resize(namelength+1,' '); + cout << out; + } + cout << endl << " "; + for (int i = 0; i < NumAntennae; i++) + { + string out = itoa(antennae[i] / (NumBands*NumAntennae*2)) + "%"; + out.resize(namelength+1,' '); + cout << out; + } + cout << endl; +} +//===============>>> ComplexMedianFlagger::FlagTimeslot <<<=============== +/* This function inspects each visibility in a cetain baseline-band +and flags on complexe distance, then determines to flag the entire baseline-band +based on the RMS of the points it didn't flag.*/ +bool ComplexMedianFlagger::FlagBaselineBand(Matrix<Bool>* Flags, + Cube<Complex>* Timeslots, + vector<double>* rms, + int* flagCounter, + double FlagThreshold, + int Position, + bool flagRMS) +{ + Vector<Float> Reals(WindowSize); + Vector<Float> Imags(WindowSize); + vector<double> RMS(NumPolarizations); + vector<int> RMSCounter(NumPolarizations); + bool FlagCompleteRow = true; + int flagcount = 0; + for (int i = NumChannels-1; i >= 0; i--) + { + bool FlagAllPolarizations = false; + for (int j = NumPolarizations-1; j >= 0; j--) + { //we need to loop twice, once to determine FlagAllCorrelations + if (!FlagAllPolarizations && PolarizationsToCheck[j]) + { + for (int k = 0; k < WindowSize; k++) + { //This might be faster in some other way ? + Reals[k] = (*Timeslots)(j, i, k).real(); + Imags[k] = (*Timeslots)(j, i, k).imag(); + } + float real = medianInPlace(Reals, false); + float imag = medianInPlace(Imags, false); + FlagAllPolarizations |= FlagThreshold < abs((*Timeslots)(j, i, Position) + - Complex(real, imag)); + } + } + for (int j = NumPolarizations-1; j >= 0; j--) + { //the second loop we set the flags or calculate RMS + if (FlagAllPolarizations) + { (*Flags)(j, i) = true; + flagcount++; + } + else + { + FlagCompleteRow = false; + (*Flags)(j, i) = false; //could check existing flag ? + double value = abs((*Timeslots)(j, i, Position)); + RMS[j] += value*value; + (RMSCounter[j])++; + } + } + } + //these need to be separated out into a different function for clarity + if (flagcount > 0.9 * NumChannels * NumPolarizations) //more as 90% bad + { + FlagCompleteRow = true; + (*Flags) = true; + flagcount = NumChannels * NumPolarizations; + } + if (!FlagCompleteRow && flagRMS) //RMSCounter > 0 + { + for (int j = NumPolarizations-1; j >= 0; j--) + { + (*rms)[j] = sqrt( RMS[j] / RMSCounter[j] ); +// if (PolarizationsToCheck[j] && ((*rms)[j] > 1.5 || (*rms)[j] <= 0.5 * NoiseLevel)) //we think this RMS value is non-physical + if (PolarizationsToCheck[j] && ((*rms)[j] > 25 || (*rms)[j] <= 0.5 * NoiseLevel)) //we think this RMS value is non-physical + { + FlagCompleteRow = true; + (*Flags) = true; + flagcount = NumChannels * NumPolarizations; + } + } + } + (*flagCounter) += flagcount; + return FlagCompleteRow; +} +//===============>>> ComplexMedianFlagger::FlagBaseline <<<=============== +/* This function iterates over baseline and band and uses FlagBaselineBand() to determine + for each one if it needs to be flagged. It treats the autocorrelations separately, + to detect entire malfunctioning telescopes. Finally it writes the flags. +*/ +void ComplexMedianFlagger::FlagTimeslot(TableIterator* flag_iter, + bool flagDatapoints, + bool flagRMS, + bool ExistingFlags, + Int Position) +{ + Cube<bool> Flags(NumPolarizations, NumChannels, NumPairs*NumBands, false); + vector<bool> FlagCompleteRow(NumPairs*NumBands); + vector<int> stats(NumPairs*NumBands); + for (int i = 0; i < NumBands; i++) + { + vector<double> rms(NumPolarizations); + vector< vector<double> > AutoCorrRMS(NumPolarizations, NumAntennae); + for (int j = 0; j < NumPolarizations; j++) // this needs to be written more elegantly + { + if ((*MSfile).itsPolarizations[j] == YX) + { PolarizationsToCheck[j] = false; // We're not checking YX because WSRT writes 0.0 into them + } + } + for(int j = 0; j < NumAntennae; j++) + { //check auto correlations + int index = i*NumPairs + BaselineIndex[pairii(j, j)]; + Matrix<Bool> flags = Flags.xyPlane(index); + FlagCompleteRow[index] = FlagBaselineBand(&flags, + &(TimeslotData[index]), + &rms, &(stats[index]), + 3000 * NoiseLevel, + Position, flagRMS); + for(int k = 0; k < NumPolarizations; k++) + { AutoCorrRMS[k][j] = rms[k]; + } + } + for(int k = 0; k < NumPolarizations; k++) //check on median + { + if (PolarizationsToCheck[k]) + { + double median = medianInPlace(Vector<double>(AutoCorrRMS[k]), false); + for(int j = 0; j < NumAntennae; j++) + { + int index = i*NumPairs + BaselineIndex[pairii(j, j)]; + if (AutoCorrRMS[k][j] < median/10 || AutoCorrRMS[k][j] > median*10) + { FlagCompleteRow[index] = true; + } + } + } + } + for (int j = 0; j < NumPolarizations; j++) // this needs to be written more elegantly + { + if ((*MSfile).itsPolarizations[j] == YX) + { PolarizationsToCheck[j] = true; // We're not checking YX + } + } + // this code coud be separated into different functions + vector< vector<double> > CrossCorrRMS(NumPolarizations, NumPairs - NumAntennae); + for(int j = 0; j < NumAntennae; j++) + { + for(int k = j+1; k < NumAntennae; k++) + { + int index = i*NumPairs + BaselineIndex[pairii(j, k)]; + Matrix<Bool> flags = Flags.xyPlane(index); + if ((BaselineLengths[BaselineIndex[pairii(j, k)]] < 3000000))//radius of the Earth in meters? WSRT sometimes has fake telescopes at 3854243 m + { //we skip the non-existent telescopes + FlagCompleteRow[index] = FlagBaselineBand(&flags, + &(TimeslotData[index]), + &rms, &(stats[index]), + (MinThreshold + (MaxThreshold - MinThreshold) + * BaselineLengths[BaselineIndex[pairii(j, k)]] + / MaxBaselineLength + ) * NoiseLevel, + Position, flagRMS); + for(int l = 0; l < NumPolarizations; l++) + { CrossCorrRMS[l][j*NumAntennae + k - ((j+1)*(j+2))/2] = rms[l]; //a very complex way of indexing, could be simplified? + } + if ( ( FlagCompleteRow[i*NumPairs + BaselineIndex[pairii(j, j)]] + ||FlagCompleteRow[i*NumPairs + BaselineIndex[pairii(k, k)]]) + &&flagRMS && !FlagCompleteRow[index]) + { //We flag it if the autocorrelation is flagged + FlagCompleteRow[index] = true; + } + } + } + } + for(int l = 0; l < NumPolarizations; l++) // check on median + { + if (PolarizationsToCheck[l]) + { + double median = medianInPlace(Vector<double>(CrossCorrRMS[l]), false); + for(int j = 0; j < NumAntennae; j++) + { + for(int k = j+1; k < NumAntennae; k++) + { + int index = i*NumPairs + BaselineIndex[pairii(j, k)]; + if (!FlagCompleteRow[index]) + { if( CrossCorrRMS[l][j*NumAntennae + k - ((j+1)*(j+2))/2] < median/10 //a very complex way of indexing, could be simplified? + || CrossCorrRMS[l][j*NumAntennae + k - ((j+1)*(j+2))/2] > median*10) + { FlagCompleteRow[index] = true; + } + } + } + } + } + } + //this code could be separated in to different functions + for(int j = 0; j < NumAntennae; j++) //write the data + { + for(int k = j; k < NumAntennae; k++) + { + int index = i*NumPairs + BaselineIndex[pairii(j, k)]; + Matrix<Bool> flags = Flags.xyPlane(index); + if (FlagCompleteRow[index]) + { + Matrix<Bool> flags = Flags.xyPlane(index); + flags = true; + Statistics(i,j,k) += NumChannels * NumPolarizations; + } + else + { Statistics(i,j,k) += stats[index]; + } + (*MSfile).WriteDataPointFlags(flag_iter, &flags, FlagCompleteRow[index], ExistingFlags); + (*flag_iter)++; + } + } + } +} + +//===============>>> ComplexMedianFlagger::UpdateTimeslotData <<<=============== +/* This function reads the visibility data for one timeslot and checks if + a mosaicing mode is active*/ +/* The datastructure Timeslotdata is rather complex because it flattens + half-filled antenna x antenna x bands matrix into a vector of NumPairs X bands length. */ +bool ComplexMedianFlagger::UpdateTimeslotData(vector<int>* OldFields, + vector<int>* OldBands, + int* TimeCounter, + Table* TimeslotTable, + double* Time) +{ + int rowcount = (*TimeslotTable).nrow(); + ROTableVector<Int> antenna1((*TimeslotTable), "ANTENNA1"); + ROTableVector<Int> antenna2((*TimeslotTable), "ANTENNA2"); + ROTableVector<Int> bandnr ((*TimeslotTable), "DATA_DESC_ID"); + ROTableVector<Int> fieldid ((*TimeslotTable), "FIELD_ID"); + ROTableVector<Double> time ((*TimeslotTable), "TIME_CENTROID");//for testing purposes + ROArrayColumn<Complex> data ((*TimeslotTable), "DATA"); + Cube<Complex> Data(NumPolarizations, NumChannels, rowcount); + + data.getColumn(Data); //We're not checking Data.nrow() Data.ncolumn(), assuming all data is the same size. + (*Time) = time(0);//for testing purposes, might be useful in the future + + bool NewField_or_Frequency = false; + + for (int i = 0; i < rowcount; i++) + { + int bi = BaselineIndex[pairii(antenna1(i), antenna2(i))]; + int field = fieldid(i); + int band = bandnr(i); + int index = (band % NumBands) * NumPairs + bi; + if ((*TimeCounter) > WindowSize - 1) + { + if (field != (*OldFields)[bi]) //pointing mosaicing + { NewField_or_Frequency = true; + } + if (band != (*OldBands)[index]) //frequency mosaicing + { NewField_or_Frequency = true; + } + } + (*OldFields)[bi] = field; + (*OldBands)[index] = band; + + TimeslotData[index].xyPlane((*TimeCounter) % WindowSize) = Data.xyPlane(i); //TimeslotData is only WindowSize size! + } + (*TimeCounter)++; //we want to reset if we detect a gap in DATA_DESC_ID or FIELD. Maybe TIME too??? + return NewField_or_Frequency; //assuming everybody is changing field or frequency at the same time! +} + +//===============>>> ComplexMedianFlagger::FlagDataOrBaselines <<<=============== +/* This function iterates over the data per timeslot and uses Flagtimeslot() + to actually flag datapoints (if flagDatapoints), and entire baselines (if flagRMS)*/ +void ComplexMedianFlagger::FlagDataOrBaselines(bool flagDatapoints, + bool flagRMS, + bool ExistingFlags) +{ + TableIterator timeslot_iter = (*MSfile).TimeslotIterator(); + TableIterator flag_iter = (*MSfile).TimeAntennaIterator(); + int TimeCounter = 0; + double Time = 0.0;//for testing purposes + vector<int> OldFields(NumPairs); //to check on multipointing and mosaicing + vector<int> OldBands(NumPairs*NumBands); //to check on multifrequency and freq mosaicing + + int step = NumTimeslots / 10 + 1; //not exact but it'll do + int row = 0; + + while (!timeslot_iter.pastEnd()) + { + Table TimeslotTable = timeslot_iter.table(); + bool NewFieldorFreq = UpdateTimeslotData(&OldFields, + &OldBands, + &TimeCounter, + &TimeslotTable, + &Time); + //cout << "Processing: " << MVTime(Time/(24*3600)).string(MVTime::YMD) << endl; //for testing purposes + + if (TimeCounter == WindowSize - 1) + { //We have filled WindowSize timeslots and need to flag the first WindowSize/2 timeslots + for (int position = 0; position < WindowSize/2; position++) + { FlagTimeslot(&flag_iter, flagDatapoints, flagRMS, ExistingFlags, position); + } + } + if (TimeCounter > WindowSize - 1) //nothing special just falg a timeslot + { FlagTimeslot(&flag_iter, flagDatapoints, flagRMS, ExistingFlags, + (TimeCounter + WindowSize/2) % WindowSize); + } + timeslot_iter++; + if (row++ % step == 0) // to tell the user how much % we have processed, + { cout << 10*(row/step) << "%" << endl; //not very accurate for low numbers of timeslots, but it'll do for now + } + if (timeslot_iter.pastEnd() || NewFieldorFreq) + { //We still need to flag the last WindowSize/2 timeslots + for (int position = WindowSize/2 + 1; position < WindowSize; position++) + { FlagTimeslot(&flag_iter, flagDatapoints, flagRMS, ExistingFlags, + (TimeCounter + position) % WindowSize); + } + TimeCounter = 0; //reset because we have changed to a new Field or frequency + } + } + ProcessStatistics(); //is there a baseline that should be flagged? +} +//===============>>> ComplexMedianFlagger <<<=============== diff --git a/Appl/CEP/CS1/CS1_pp_lib/src/FlaggerStatistics.h b/Appl/CEP/CS1/CS1_pp_lib/src/FlaggerStatistics.h new file mode 100644 index 0000000000000000000000000000000000000000..0619007dc1b81bd000b9c0dc48536c5bc891836e --- /dev/null +++ b/Appl/CEP/CS1/CS1_pp_lib/src/FlaggerStatistics.h @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (C) 2006 by ASTRON, Adriaan Renting * + * renting@astron.nl * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef __FLAGGER_COMPLEXMEDIANFLAGGER_H__ +#define __FLAGGER_COMPLEXMEDIANFLAGGER_H__ + +#include <casa/Arrays.h> +#include <utility> +#include <vector> +#include <list> +#include <map> +#include "MS_File.h" + +namespace WSRT +{ + using casa::Cube; + using casa::Matrix; + using casa::Complex; + using casa::Int; + using casa::Double; + using casa::Bool; + using casa::Table; + using std::list; + using std::vector; + + typedef pair<int, int> pairii; + + class ComplexMedianFlagger + { + public: + ComplexMedianFlagger(MS_File* MSfile, + int InputWindowSize, + bool UseOnlyXpolarizations, + double InputMinThreshold, + double InputMaxThreshold); + ~ComplexMedianFlagger(); + + void FlagDataOrBaselines(bool flagDatapoints, + bool flagRMS, + bool ExistingFlags); + + protected: + int NumAntennae; + int NumPairs; + int NumBands; + int NumChannels; + int NumPolarizations; + int WindowSize; + int NumTimeslots; + double MinThreshold; + double MaxThreshold; + double MaxBaselineLength; + double NoiseLevel; + vector<double> BaselineLengths; + vector<pairii> PairsIndex; + map<pairii, int> BaselineIndex; + vector< Cube<Complex> > TimeslotData; + vector< bool > PolarizationsToCheck; + vector<casa::String> AntennaNames; + Cube< int > Statistics; + MS_File* MSfile; + + void DeterminePolarizationsToCheck(Bool UseOnlyXpolarizations); + void ComputeBaselineLengths(); + void ProcessStatistics(); + void FlagTimeslot(casa::TableIterator* flag_iter, + bool flagDatapoints, + bool flagRMS, + bool ExistingFlags, + int Position); + bool FlagBaselineBand(Matrix<Bool>* Flags, + Cube<Complex>* Timeslots, + vector<double>* rms, + int* flagCounter, + double FlagThreshold, + int Position, + bool flagRMS); + bool UpdateTimeslotData(vector<int>* OldFields, + vector<int>* OldBands, + int* TimeCounter, + Table* TimeslotTable, + double* Time); + private: + }; // ComplexMedianFlagger +}; // namespace WSRT + +#endif // __FLAGGER_COMPLEXMEDIANFLAGGER_H__ diff --git a/Appl/CEP/CS1/CS1_pp_lib/src/MsInfo.cc b/Appl/CEP/CS1/CS1_pp_lib/src/MsInfo.cc new file mode 100644 index 0000000000000000000000000000000000000000..926f0f63c874a35244e993183ff98ac39e60beca --- /dev/null +++ b/Appl/CEP/CS1/CS1_pp_lib/src/MsInfo.cc @@ -0,0 +1,156 @@ +/*************************************************************************** + * Copyright (C) 2007 by ASTRON, Adriaan Renting * + * renting@astron.nl * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include <casa/BasicMath/Math.h> +#include <casa/Arrays.h> + +#include <iostream> + +#include "MsInfo.h" + +using namespace LOFAR; +using namespace casa; + +//===============>>> Ms_Info::Ms_Info <<<=============== + +MsInfo::MsInfo(const std::string& msname) +{ + MsName = msname; + MaxBaselineLength = 0.0; + NumSamples = 0; + NumAntennae = 0; + NumFields = 0; + NumBands = 0; + NumChannels = 0; + NumPolarizations = 0; + NumPairs = 0; + NumTimeslots = 0; + NoiseLevel = 0.0; +} + +//===============>>> Ms_Info::~Ms_Info <<<=============== + +MsInfo::~MsInfo() +{ +} + +//===============>>> Ms_Info::update <<<=============== + +void MsInfo::Update(void) +{ + MeasurementSet MS(MsName); + + //Number of samples + NumSamples = MS.nrow(); + //Number of Fields + MSField fields = MS.field(); + NumFields = fields.nrow(); + + //Number of Antennae + MSAntenna antennae = MS.antenna(); + NumAntennae = antennae.nrow(); + + //Antenna Names + ROScalarColumn<String> ANT_NAME_col(antennae, "NAME"); + Vector<String> ant_names = ANT_NAME_col.getColumn(); + ant_names.tovector(AntennaNames); + + //Number of channels in the Band + MSSpectralWindow spectral_window = MS.spectralWindow(); + ROScalarColumn<Int> NUM_CHAN_col(spectral_window, "NUM_CHAN"); + NumChannels = NUM_CHAN_col(0); + + //Number of polarizations + MSPolarization polarization = MS.polarization(); + ROScalarColumn<Int> NUM_CORR_col(polarization, "NUM_CORR"); + NumPolarizations = NUM_CORR_col(0); + ROArrayColumn<Int> CORR_TYPE_col(polarization, "CORR_TYPE"); + Polarizations.resize(NumPolarizations); + CORR_TYPE_col.get(0, Polarizations); + + //calculate theoretical noise level + ROScalarColumn<Double> EXPOSURE_col(MS, "EXPOSURE"); + Double exposure = EXPOSURE_col(0); + + ROScalarColumn<Double> TOTAL_BANDWIDTH_col(spectral_window, "TOTAL_BANDWIDTH"); + Double bandwidth = TOTAL_BANDWIDTH_col(0) / NumChannels; + + NoiseLevel = 1.0 / sqrt(bandwidth * exposure); + + //calculate number of timeslots + ROScalarColumn<Double> INTERVAL_col(MS, "INTERVAL"); + Double Interval = INTERVAL_col(0); + + //Number of timeslots + ROScalarColumn<Double> TIME_CENTROID_col(MS, "TIME_CENTROID"); + Double firstdate = TIME_CENTROID_col(0); + Double lastdate = TIME_CENTROID_col(NumSamples-1); + + NumTimeslots = (int)((lastdate-firstdate)/Interval) + 1; + + //calculate number of baselines. + NumPairs = (NumAntennae) * (NumAntennae + 1) / 2; //Triangular numbers formula + + //calculate number of Bands + NumBands = NumSamples / (NumPairs * NumTimeslots); + + ComputeBaselineLengths(MS); +} + +//===============>>> MS_Info::PrintInfo <<<=============== + +void MsInfo::PrintInfo(void) +{ + std::cout << "NumSamples: " << NumSamples << std::endl; + std::cout << "NumFields: " << NumFields << std::endl; + std::cout << "NumAntennae: " << NumAntennae << std::endl; + std::cout << "NumChannels: " << NumChannels << std::endl; + std::cout << "NumPolarizations: " << NumPolarizations << std::endl; + std::cout << "Noiselevel: " << NoiseLevel << std::endl; + std::cout << "Interval: " << Interval << std::endl; + std::cout << "Numtimeslots: " << NumTimeslots << std::endl; + std::cout << "NumPairs: " << NumPairs << std::endl; + std::cout << "NumBands: " << NumBands << std::endl; +} + +//===============>>> MS_Info::ComputeBaselineLengths <<<=============== +/* compute baseline lengths, and determine the longest one.*/ + +void MsInfo::ComputeBaselineLengths(casa::MeasurementSet& MS) +{ + BaselineLengths.resize(NumPairs); + //Antenna positions + MSAntenna antenna = MS.antenna(); + ROArrayColumn<Double> position(antenna, "POSITION"); + for (int i = 0; i < NumAntennae; i++ ) + { + for (int j = i; j < NumAntennae; j++) + { + Vector<Double> p(position(i) - position(j)); + double temp = sqrt(p(0)*p(0) + p(1)*p(1) + p(2)*p(2)); + BaselineLengths[BaselineIndex[baseline_t(i, j)]] = temp; + if (temp > MaxBaselineLength && temp < 3000000) //radius of the Earth in meters? WSRT sometimes has fake telescopes at 3854243 + { MaxBaselineLength = temp; // non-existent antenna's can have position (0,0,0) + } + } + } +} + +//===============>>> MsInfo <<<=============== + diff --git a/Appl/CEP/CS1/CS1_pp_lib/src/MsInfo.h b/Appl/CEP/CS1/CS1_pp_lib/src/MsInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..e3ca327e2d5c5fd95b9b2f03820c4b749764ba2f --- /dev/null +++ b/Appl/CEP/CS1/CS1_pp_lib/src/MsInfo.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2007 by ASTRON, Adriaan Renting * + * renting@astron.nl * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef __CS1_PP_MS_INFO_H__ +#define __CS1_PP_MS_INFO_H__ + +#include <ms/MeasurementSets.h> +#include <tables/Tables.h> +#include <utility> +#include <vector> +#include <string> +#include <map> + +namespace LOFAR +{ + typedef std::pair<int, int> baseline_t; + + class MsInfo + { + public: + MsInfo(const std::string& msname); + ~MsInfo(); + + int NumSamples; + int NumAntennae; + int NumFields; + int NumBands; + int NumChannels; + int NumPolarizations; + int NumPairs; + int NumTimeslots; + double NoiseLevel; + std::vector<casa::String> AntennaNames; + casa::Vector<casa::Int> Polarizations; + double MaxBaselineLength; + std::vector<double> BaselineLengths; + std::vector<baseline_t> PairsIndex; + std::map<baseline_t, int> BaselineIndex; + + void Update(void); + void PrintInfo(void); + + protected: + private: + std::string MsName; + double Interval; + void ComputeBaselineLengths(casa::MeasurementSet& MS); + }; // MsInfo +}; // namespace LOFAR + +#endif // __CS1_PP_MS_INFO_H__