Double GetRealScalar(pMatrix ppm, int element) { rMatrix pm = ppm[element]; if ((GetM(pm) == 1) && (GetN(pm) == 1) && (IsNumeric(pm)) && (!IsComplex(pm)) ) { return(mxGetScalar(pm)); } else { ErrMsgTxt("Expecting a scalar argument."); } return(0.0); }
/** \brief MATLAB entry point. * * This is the function that MATLAB actually calls when executing the included * functions. This function checks the validity of the inputs and outputs, * and calls the actual worker function. * * \param nlhs the number of expected output arguments. * \param plhs place holders for the output arguments. * \param nrhs the number of input arguments. * \param prhs the actual input arguments. */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs < 2) mexErrMsgTxt("Too few arguments in MEXCALCESIG.\n"); if (nrhs > 3) mexErrMsgTxt("Too many arguments in MEXCALCESIG.\n"); if (nrhs < 0) mexErrMsgTxt("Too few arguments in MEXCALCESIG.\n"); if (nlhs > 1) mexErrMsgTxt("Too many outputs in MEXCALCESIG.\n"); TmexArray P(prhs[0]), G(prhs[1]); if (P.size() != G.size()) mexErrMsgTxt("P and G must be the same size in MEXCALCESIG.\n"); double size_mult = 1; if (nrhs > 2) { TmexArray S(prhs[2]); if (S.size() == 1) { size_mult = S[0]; } } if(!IsComplex(P) && !IsComplex(G) ) plhs[0] = mxCreateDoubleMatrix(static_cast<int>(P.size()),static_cast<int>(size_mult*P.size()),mxREAL); else plhs[0] = mxCreateDoubleMatrix(static_cast<int>(P.size()),static_cast<int>(size_mult*P.size()),mxCOMPLEX); TmexArray Esig(plhs[0]); CalcEsig(Esig, P, G); }
BOOL CXaraFileRectangle::WriteRectangle(BaseCamelotFilter * pFilter, NodeRegularShape * pShape) { BOOL ok; // we need to determine how is rectangle has been altered, i.e. rotated, rounded, stellated // or reformed. using this information we jump to one of the following functions to write // the information out for us. const INT32 REFORMED = 0x1; const INT32 STELLATED = 0x2; const INT32 ROUNDED = 0x4; const INT32 COMPLEX = 0x8; INT32 RectangleType = 0; if (IsReformed(pShape)) RectangleType |= REFORMED; if (IsStellated(pShape)) RectangleType |= STELLATED; if (IsRounded(pShape)) RectangleType |= ROUNDED; if (IsComplex(pShape)) RectangleType |= COMPLEX; switch (RectangleType) { case 0 : ok = WriteRectangleSimple(pFilter, pShape); break; case REFORMED : ok = WriteRectangleSimpleReformed(pFilter, pShape); break; case STELLATED : ok = WriteRectangleSimpleStellated(pFilter, pShape); break; case STELLATED|REFORMED : ok = WriteRectangleSimpleStellatedReformed(pFilter, pShape); break; case ROUNDED : ok = WriteRectangleSimpleRounded(pFilter, pShape); break; case ROUNDED|REFORMED : ok = WriteRectangleSimpleRoundedReformed(pFilter, pShape); break; case ROUNDED|STELLATED : ok = WriteRectangleSimpleRoundedStellated(pFilter, pShape); break; case ROUNDED|STELLATED|REFORMED : ok = WriteRectangleSimpleRoundedStellatedReformed(pFilter, pShape); break; case COMPLEX : ok = WriteRectangleComplex(pFilter, pShape); break; case COMPLEX|REFORMED : ok = WriteRectangleComplexReformed(pFilter, pShape); break; case COMPLEX|STELLATED : ok = WriteRectangleComplexStellated(pFilter, pShape); break; case COMPLEX|STELLATED|REFORMED : ok = WriteRectangleComplexStellatedReformed(pFilter, pShape); break; case COMPLEX|ROUNDED : ok = WriteRectangleComplexRounded(pFilter, pShape); break; case COMPLEX|ROUNDED|REFORMED : ok = WriteRectangleComplexRoundedReformed(pFilter, pShape); break; case COMPLEX|ROUNDED|STELLATED : ok = WriteRectangleComplexRoundedStellated(pFilter, pShape); break; case COMPLEX|ROUNDED|STELLATED|REFORMED : ok = WriteRectangleComplexRoundedStellatedReformed(pFilter, pShape); break; default : ok = WriteShapeInvalid(pFilter, pShape); break; } return ok; }
void WSMSGridder::Predict(double* real, double* imaginary) { if(imaginary==0 && IsComplex()) throw std::runtime_error("Missing imaginary in complex prediction"); if(imaginary!=0 && !IsComplex()) throw std::runtime_error("Imaginary specified in non-complex prediction"); MSData* msDataVector = new MSData[MeasurementSetCount()]; _hasFrequencies = false; for(size_t i=0; i!=MeasurementSetCount(); ++i) initializeMeasurementSet(i, msDataVector[i]); double minW = msDataVector[0].minW; double maxW = msDataVector[0].maxW; for(size_t i=1; i!=MeasurementSetCount(); ++i) { if(msDataVector[i].minW < minW) minW = msDataVector[i].minW; if(msDataVector[i].maxW > maxW) maxW = msDataVector[i].maxW; } _gridder = std::unique_ptr<WStackingGridder>(new WStackingGridder(_actualInversionWidth, _actualInversionHeight, _actualPixelSizeX, _actualPixelSizeY, _cpuCount, _imageBufferAllocator, AntialiasingKernelSize(), OverSamplingFactor())); _gridder->SetGridMode(_gridMode); if(_denormalPhaseCentre) _gridder->SetDenormalPhaseCentre(_phaseCentreDL, _phaseCentreDM); _gridder->SetIsComplex(IsComplex()); //_imager->SetImageConjugatePart(Polarization() == Polarization::YX && IsComplex()); _gridder->PrepareWLayers(WGridSize(), double(_memSize)*(7.0/10.0), minW, maxW); if(Verbose()) { for(size_t i=0; i!=MeasurementSetCount(); ++i) countSamplesPerLayer(msDataVector[i]); } double *resizedReal = 0, *resizedImag = 0; if(ImageWidth()!=_actualInversionWidth || ImageHeight()!=_actualInversionHeight) { FFTResampler resampler(ImageWidth(), ImageHeight(), _actualInversionWidth, _actualInversionHeight, _cpuCount); if(imaginary == 0) { resizedReal = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight()); resampler.RunSingle(real, resizedReal); real = resizedReal; } else { resizedReal = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight()); resizedImag = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight()); resampler.Start(); resampler.AddTask(real, resizedReal); resampler.AddTask(imaginary, resizedImag); resampler.Finish(); real = resizedReal; imaginary = resizedImag; } } for(size_t pass=0; pass!=_gridder->NPasses(); ++pass) { std::cout << "Fourier transforms for pass " << pass << "... "; if(Verbose()) std::cout << '\n'; else std::cout << std::flush; if(imaginary == 0) _gridder->InitializePrediction(real); else _gridder->InitializePrediction(real, imaginary); _gridder->StartPredictionPass(pass); std::cout << "Predicting...\n"; for(size_t i=0; i!=MeasurementSetCount(); ++i) predictMeasurementSet(msDataVector[i]); } if(ImageWidth()!=_actualInversionWidth || ImageHeight()!=_actualInversionHeight) { _imageBufferAllocator->Free(resizedReal); _imageBufferAllocator->Free(resizedImag); } size_t totalRowsWritten = 0, totalMatchingRows = 0; for(size_t i=0; i!=MeasurementSetCount(); ++i) { totalRowsWritten += msDataVector[i].totalRowsProcessed; totalMatchingRows += msDataVector[i].matchingRows; } std::cout << "Total rows written: " << totalRowsWritten; if(totalMatchingRows != 0) std::cout << " (overhead: " << std::max(0.0, round(totalRowsWritten * 100.0 / totalMatchingRows - 100.0)) << "%)"; std::cout << '\n'; delete[] msDataVector; }
void WSMSGridder::initializeMeasurementSet(size_t msIndex, WSMSGridder::MSData& msData) { MSProvider& msProvider = MeasurementSet(msIndex); msData.msProvider = &msProvider; casacore::MeasurementSet& ms(msProvider.MS()); if(ms.nrow() == 0) throw std::runtime_error("Table has no rows (no data)"); /** * Read some meta data from the measurement set */ casacore::MSAntenna aTable = ms.antenna(); size_t antennaCount = aTable.nrow(); if(antennaCount == 0) throw std::runtime_error("No antennae in set"); casacore::MPosition::ROScalarColumn antPosColumn(aTable, aTable.columnName(casacore::MSAntennaEnums::POSITION)); casacore::MPosition ant1Pos = antPosColumn(0); msData.bandData = MultiBandData(ms.spectralWindow(), ms.dataDescription()); if(Selection(msIndex).HasChannelRange()) { msData.startChannel = Selection(msIndex).ChannelRangeStart(); msData.endChannel = Selection(msIndex).ChannelRangeEnd(); std::cout << "Selected channels: " << msData.startChannel << '-' << msData.endChannel << '\n'; const BandData& firstBand = msData.bandData.FirstBand(); if(msData.startChannel >= firstBand.ChannelCount() || msData.endChannel > firstBand.ChannelCount() || msData.startChannel == msData.endChannel) { std::ostringstream str; str << "An invalid channel range was specified! Measurement set only has " << firstBand.ChannelCount() << " channels, requested imaging range is " << msData.startChannel << " -- " << msData.endChannel << '.'; throw std::runtime_error(str.str()); } } else { msData.startChannel = 0; msData.endChannel = msData.bandData.FirstBand().ChannelCount(); } casacore::MEpoch::ROScalarColumn timeColumn(ms, ms.columnName(casacore::MSMainEnums::TIME)); const MultiBandData selectedBand = msData.SelectedBand(); if(_hasFrequencies) { _freqLow = std::min(_freqLow, selectedBand.LowestFrequency()); _freqHigh = std::max(_freqHigh, selectedBand.HighestFrequency()); _bandStart = std::min(_bandStart, selectedBand.BandStart()); _bandEnd = std::max(_bandEnd, selectedBand.BandEnd()); _startTime = std::min(_startTime, msProvider.StartTime()); } else { _freqLow = selectedBand.LowestFrequency(); _freqHigh = selectedBand.HighestFrequency(); _bandStart = selectedBand.BandStart(); _bandEnd = selectedBand.BandEnd(); _startTime = msProvider.StartTime(); _hasFrequencies = true; } casacore::MSField fTable(ms.field()); casacore::MDirection::ROScalarColumn phaseDirColumn(fTable, fTable.columnName(casacore::MSFieldEnums::PHASE_DIR)); casacore::MDirection phaseDir = phaseDirColumn(Selection(msIndex).FieldId()); casacore::MEpoch curtime = timeColumn(0); casacore::MeasFrame frame(ant1Pos, curtime); casacore::MDirection::Ref j2000Ref(casacore::MDirection::J2000, frame); casacore::MDirection j2000 = casacore::MDirection::Convert(phaseDir, j2000Ref)(); casacore::Vector<casacore::Double> j2000Val = j2000.getValue().get(); _phaseCentreRA = j2000Val[0]; _phaseCentreDec = j2000Val[1]; if(fTable.keywordSet().isDefined("WSCLEAN_DL")) _phaseCentreDL = fTable.keywordSet().asDouble(casacore::RecordFieldId("WSCLEAN_DL")); else _phaseCentreDL = 0.0; if(fTable.keywordSet().isDefined("WSCLEAN_DM")) _phaseCentreDM = fTable.keywordSet().asDouble(casacore::RecordFieldId("WSCLEAN_DM")); else _phaseCentreDM = 0.0; _denormalPhaseCentre = _phaseCentreDL != 0.0 || _phaseCentreDM != 0.0; if(_denormalPhaseCentre) std::cout << "Set has denormal phase centre: dl=" << _phaseCentreDL << ", dm=" << _phaseCentreDM << '\n'; std::cout << "Determining min and max w & theoretical beam size... " << std::flush; msData.maxW = 0.0; msData.minW = 1e100; double maxBaseline = 0.0; std::vector<float> weightArray(selectedBand.MaxChannels()); msProvider.Reset(); while(msProvider.CurrentRowAvailable()) { size_t dataDescId; double uInM, vInM, wInM; msProvider.ReadMeta(uInM, vInM, wInM, dataDescId); const BandData& curBand = selectedBand[dataDescId]; double wHi = fabs(wInM / curBand.SmallestWavelength()); double wLo = fabs(wInM / curBand.LongestWavelength()); double baselineInM = sqrt(uInM*uInM + vInM*vInM + wInM*wInM); double halfWidth = 0.5*ImageWidth(), halfHeight = 0.5*ImageHeight(); if(wHi > msData.maxW || wLo < msData.minW || baselineInM / curBand.SmallestWavelength() > maxBaseline) { msProvider.ReadWeights(weightArray.data()); const float* weightPtr = weightArray.data(); for(size_t ch=0; ch!=curBand.ChannelCount(); ++ch) { if(*weightPtr != 0.0) { const double wavelength = curBand.ChannelWavelength(ch); double uInL = uInM/wavelength, vInL = vInM/wavelength, wInL = wInM/wavelength, x = uInL * PixelSizeX() * ImageWidth(), y = vInL * PixelSizeY() * ImageHeight(), imagingWeight = this->PrecalculatedWeightInfo()->GetWeight(uInL, vInL); if(imagingWeight != 0.0) { if(floor(x) > -halfWidth && ceil(x) < halfWidth && floor(y) > -halfHeight && ceil(y) < halfHeight) { msData.maxW = std::max(msData.maxW, fabs(wInL)); msData.minW = std::min(msData.minW, fabs(wInL)); maxBaseline = std::max(maxBaseline, baselineInM / wavelength); } } } ++weightPtr; } } msProvider.NextRow(); } if(msData.minW == 1e100) { msData.minW = 0.0; msData.maxW = 0.0; } _beamSize = 1.0 / maxBaseline; std::cout << "DONE (w=[" << msData.minW << ":" << msData.maxW << "] lambdas, maxuvw=" << maxBaseline << " lambda, beam=" << Angle::ToNiceString(_beamSize) << ")\n"; if(HasWLimit()) { msData.maxW *= (1.0 - WLimit()); if(msData.maxW < msData.minW) msData.maxW = msData.minW; } _actualInversionWidth = ImageWidth(); _actualInversionHeight = ImageHeight(); _actualPixelSizeX = PixelSizeX(); _actualPixelSizeY = PixelSizeY(); if(SmallInversion()) { double totalWidth = _actualInversionWidth * _actualPixelSizeX, totalHeight = _actualInversionHeight * _actualPixelSizeY; // Calc min res based on Nyquist sampling rate size_t minResX = size_t(ceil(totalWidth*2 / _beamSize)); if(minResX%4 != 0) minResX += 4 - (minResX%4); size_t minResY = size_t(ceil(totalHeight*2 / _beamSize)); if(minResY%4 != 0) minResY += 4 - (minResY%4); if(minResX < _actualInversionWidth || minResY < _actualInversionHeight) { _actualInversionWidth = std::max(std::min(minResX, _actualInversionWidth), size_t(32)); _actualInversionHeight = std::max(std::min(minResY, _actualInversionHeight), size_t(32)); std::cout << "Setting small inversion image size of " << _actualInversionWidth << " x " << _actualInversionHeight << "\n"; _actualPixelSizeX = totalWidth / _actualInversionWidth; _actualPixelSizeY = totalHeight / _actualInversionHeight; } else { std::cout << "Small inversion enabled, but inversion resolution already smaller than beam size: not using optimization.\n"; } } if(Verbose() || !HasWGridSize()) { double maxL = ImageWidth() * PixelSizeX() * 0.5 + fabs(_phaseCentreDL), maxM = ImageHeight() * PixelSizeY() * 0.5 + fabs(_phaseCentreDM), lmSq = maxL * maxL + maxM * maxM; double cMinW = IsComplex() ? -msData.maxW : msData.minW; double radiansForAllLayers; if(lmSq < 1.0) radiansForAllLayers = 2 * M_PI * (msData.maxW - cMinW) * (1.0 - sqrt(1.0 - lmSq)); else radiansForAllLayers = 2 * M_PI * (msData.maxW - cMinW); size_t suggestedGridSize = size_t(ceil(radiansForAllLayers)); if(suggestedGridSize == 0) suggestedGridSize = 1; if(suggestedGridSize < _cpuCount) { // When nwlayers is lower than the nr of cores, we cannot parallellize well. // However, we don't want extra w-layers if we are low on mem, as that might slow down the process double memoryRequired = double(_cpuCount) * double(sizeof(double))*double(_actualInversionWidth*_actualInversionHeight); if(4.0 * memoryRequired < double(_memSize)) { std::cout << "The theoretically suggested number of w-layers (" << suggestedGridSize << ") is less than the number of availables\n" "cores (" << _cpuCount << "). Changing suggested number of w-layers to " << _cpuCount << ".\n"; suggestedGridSize = _cpuCount; } else { std::cout << "The theoretically suggested number of w-layers (" << suggestedGridSize << ") is less than the number of availables\n" "cores (" << _cpuCount << "), but there is not enough memory available to increase the number of w-layers.\n" "Not all cores can be used efficiently.\n"; } } if(Verbose()) std::cout << "Suggested number of w-layers: " << ceil(suggestedGridSize) << '\n'; if(!HasWGridSize()) SetWGridSize(suggestedGridSize); } }
void WSMSGridder::Invert() { MSData* msDataVector = new MSData[MeasurementSetCount()]; _hasFrequencies = false; for(size_t i=0; i!=MeasurementSetCount(); ++i) initializeMeasurementSet(i, msDataVector[i]); double minW = msDataVector[0].minW; double maxW = msDataVector[0].maxW; for(size_t i=1; i!=MeasurementSetCount(); ++i) { if(msDataVector[i].minW < minW) minW = msDataVector[i].minW; if(msDataVector[i].maxW > maxW) maxW = msDataVector[i].maxW; } _gridder = std::unique_ptr<WStackingGridder>(new WStackingGridder(_actualInversionWidth, _actualInversionHeight, _actualPixelSizeX, _actualPixelSizeY, _cpuCount, _imageBufferAllocator, AntialiasingKernelSize(), OverSamplingFactor())); _gridder->SetGridMode(_gridMode); if(_denormalPhaseCentre) _gridder->SetDenormalPhaseCentre(_phaseCentreDL, _phaseCentreDM); _gridder->SetIsComplex(IsComplex()); //_imager->SetImageConjugatePart(Polarization() == Polarization::YX && IsComplex()); _gridder->PrepareWLayers(WGridSize(), double(_memSize)*(7.0/10.0), minW, maxW); if(Verbose()) { for(size_t i=0; i!=MeasurementSetCount(); ++i) countSamplesPerLayer(msDataVector[i]); } _totalWeight = 0.0; for(size_t pass=0; pass!=_gridder->NPasses(); ++pass) { std::cout << "Gridding pass " << pass << "... "; if(Verbose()) std::cout << '\n'; else std::cout << std::flush; _inversionWorkLane.reset(new ao::lane<InversionWorkItem>(2048)); _gridder->StartInversionPass(pass); for(size_t i=0; i!=MeasurementSetCount(); ++i) { _inversionWorkLane->clear(); MSData& msData = msDataVector[i]; const MultiBandData selectedBand(msData.SelectedBand()); boost::thread thread(&WSMSGridder::workThreadParallel, this, &selectedBand); gridMeasurementSet(msData); _inversionWorkLane->write_end(); thread.join(); } _inversionWorkLane.reset(); std::cout << "Fourier transforms...\n"; _gridder->FinishInversionPass(); } if(Verbose()) { size_t totalRowsRead = 0, totalMatchingRows = 0; for(size_t i=0; i!=MeasurementSetCount(); ++i) { totalRowsRead += msDataVector[i].totalRowsProcessed; totalMatchingRows += msDataVector[i].matchingRows; } std::cout << "Total rows read: " << totalRowsRead; if(totalMatchingRows != 0) std::cout << " (overhead: " << std::max(0.0, round(totalRowsRead * 100.0 / totalMatchingRows - 100.0)) << "%)"; std::cout << '\n'; } if(NormalizeForWeighting()) _gridder->FinalizeImage(1.0/_totalWeight, false); else { std::cout << "Not dividing by normalization factor of " << _totalWeight << ".\n"; _gridder->FinalizeImage(1.0, true); } if(ImageWidth()!=_actualInversionWidth || ImageHeight()!=_actualInversionHeight) { FFTResampler resampler(_actualInversionWidth, _actualInversionHeight, ImageWidth(), ImageHeight(), _cpuCount); if(IsComplex()) { double *resizedReal = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight()); double *resizedImag = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight()); resampler.Start(); resampler.AddTask(_gridder->RealImage(), resizedReal); resampler.AddTask(_gridder->ImaginaryImage(), resizedImag); resampler.Finish(); _gridder->ReplaceRealImageBuffer(resizedReal); _gridder->ReplaceImaginaryImageBuffer(resizedImag); } else { double *resized = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight()); resampler.RunSingle(_gridder->RealImage(), resized); _gridder->ReplaceRealImageBuffer(resized); } } delete[] msDataVector; }
int GetRealSparseVector(pMatrix ppm, int element, Double *vec, int *index, int start, int len, int col) { int j, k, k1, m, n, start1, count = 0; int *ir, *jc; double *pr, *pr0; rMatrix pm = ppm[element]; m = GetM(pm); n = GetN(pm); if ( ((col == 0) && (((m != 1) && (n != 1)) || ((m == 1) && (n > len)) || ((n == 1) && (m > len)))) || ((col != 0) && ((m > len) || (col > n))) || !IsNumeric(pm) || IsComplex(pm) ) { ErrMsgTxt("invalid vector."); } pr = GetPr(pm); if (!IsSparse(pm)) { if ((((n == 1) || (col != 0)) && (m != len)) || ((col == 0) && (m == 1) && (n != len))) ErrMsgTxt("invalid vector."); if (col) pr += (col - 1) * m; for (k = 0; k < len; k++, pr++) { if (*pr) { *(vec++) = *pr; *(index++) = start + k; count++; } } } else if (IsSparse(pm)) { int j1, j2; jc = mxGetJc(pm); ir = mxGetIr(pm); pr0 = pr; if (col == 0) { j1 = 0; j2 = n; } else { j1 = col - 1; j2 = col; } for (j = j1; j < j2; j++) { k = jc[j]; k1 = jc[j + 1]; pr = pr0 + k; start1 = start; if (col == 0) start1 += j * m; for (; k < k1; k++, pr++, vec++, index++) { *vec = *pr; *index = start1 + ir[k]; count++; } } } else { ErrMsgTxt("Can't figure out this matrix."); } return(count); }