void SBMoffat::SBMoffatImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, double dkxy, double ky0, double dky, double dkyx) const { dbg<<"SBMoffat fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<" + j * "<<dkxy<<std::endl; dbg<<"ky = "<<ky0<<" + i * "<<dkyx<<" + j * "<<dky<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<std::complex<double>,1,tmv::NonConj> It; kx0 *= _rD; dkx *= _rD; dkxy *= _rD; ky0 *= _rD; dky *= _rD; dkyx *= _rD; It valit = val.linearView().begin(); for (int j=0;j<n;++j,kx0+=dkxy,ky0+=dky) { double kx = kx0; double ky = ky0; for (int i=0;i<m;++i,kx+=dkx,ky+=dkyx) { double ksq = kx*kx + ky*ky; *valit++ = _knorm * (this->*_kV)(ksq); } } }
void SBGaussian::SBGaussianImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, int izero, double ky0, double dky, int jzero) const { dbg<<"SBGaussian fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<", izero = "<<izero<<std::endl; dbg<<"ky = "<<ky0<<" + j * "<<dky<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillKValueQuadrant(val,kx0,dkx,izero,ky0,dky,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; kx0 *= _sigma; dkx *= _sigma; ky0 *= _sigma; dky *= _sigma; tmv::Vector<double> gauss_kx(m); It kxit = gauss_kx.begin(); for (int i=0;i<m;++i,kx0+=dkx) *kxit++ = exp(-0.5 * kx0*kx0); tmv::Vector<double> gauss_ky(n); It kyit = gauss_ky.begin(); for (int j=0;j<n;++j,ky0+=dky) *kyit++ = exp(-0.5 * ky0*ky0); val = _flux * gauss_kx ^ gauss_ky; } }
void SBKolmogorov::SBKolmogorovImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, double dkxy, double ky0, double dky, double dkyx) const { dbg<<"SBKolmogorov fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<" + j * "<<dkxy<<std::endl; dbg<<"ky = "<<ky0<<" + i * "<<dkyx<<" + j * "<<dky<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<std::complex<double>,1,tmv::NonConj> It; kx0 *= _inv_k0; dkx *= _inv_k0; dkxy *= _inv_k0; ky0 *= _inv_k0; dky *= _inv_k0; dkyx *= _inv_k0; It valit = val.linearView().begin(); for (int j=0;j<n;++j,kx0+=dkxy,ky0+=dky) { double kx = kx0; double ky = ky0; for (int i=0;i<m;++i,kx+=dkx,ky+=dkyx) *valit++ = _flux * _info->kValue(kx*kx+ky*ky); } }
void SBGaussian::SBGaussianImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBGaussian fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<" + j * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + i * "<<dyx<<" + j * "<<dy<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; x0 *= _inv_sigma; dx *= _inv_sigma; dxy *= _inv_sigma; y0 *= _inv_sigma; dy *= _inv_sigma; dyx *= _inv_sigma; It valit = val.linearView().begin(); for (int j=0;j<n;++j,x0+=dxy,y0+=dy) { double x = x0; double y = y0; for (int i=0;i<m;++i,x+=dx,y+=dyx) *valit++ = _norm * std::exp( -0.5 * (x*x + y*y) ); } }
void SBMoffat::SBMoffatImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, int izero, double y0, double dy, int jzero) const { dbg<<"SBMoffat fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<", izero = "<<izero<<std::endl; dbg<<"y = "<<y0<<" + j * "<<dy<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillXValueQuadrant(val,x0,dx,izero,y0,dy,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; x0 *= _inv_rD; dx *= _inv_rD; y0 *= _inv_rD; dy *= _inv_rD; for (int j=0;j<n;++j,y0+=dy) { double x = x0; double ysq = y0*y0; It valit = val.col(j).begin(); for (int i=0;i<m;++i,x+=dx) { double rsq = x*x + ysq; if (rsq > _maxRrD_sq) *valit++ = 0.; else *valit++ = _norm / _pow_beta(1.+rsq, _beta); } } } }
void SBMoffat::SBMoffatImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBMoffat fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<" + j * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + i * "<<dyx<<" + j * "<<dy<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; x0 *= _inv_rD; dx *= _inv_rD; dxy *= _inv_rD; y0 *= _inv_rD; dy *= _inv_rD; dyx *= _inv_rD; It valit = val.linearView().begin(); for (int j=0;j<n;++j,x0+=dxy,y0+=dy) { double x = x0; double y = y0; for (int i=0;i<m;++i,x+=dx,y+=dyx) { double rsq = x*x + y*y; if (rsq > _maxRrD_sq) *valit++ = 0.; else *valit++ = _norm / _pow_beta(1.+rsq, _beta); } } }
void SBKolmogorov::SBKolmogorovImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, int izero, double ky0, double dky, int jzero) const { dbg<<"SBKolmogorov fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<", izero = "<<izero<<std::endl; dbg<<"ky = "<<ky0<<" + j * "<<dky<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillKValueQuadrant(val,kx0,dkx,izero,ky0,dky,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<std::complex<double>,1,tmv::NonConj> It; kx0 *= _inv_k0; dkx *= _inv_k0; ky0 *= _inv_k0; dky *= _inv_k0; for (int j=0;j<n;++j,ky0+=dky) { double kx = kx0; double kysq = ky0*ky0; It valit = val.col(j).begin(); for (int i=0;i<m;++i,kx+=dkx) *valit++ = _flux * _info->kValue(kx*kx + kysq); } } }
void SBGaussian::SBGaussianImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, int izero, double y0, double dy, int jzero) const { dbg<<"SBGaussian fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<", izero = "<<izero<<std::endl; dbg<<"y = "<<y0<<" + j * "<<dy<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillXValueQuadrant(val,x0,dx,izero,y0,dy,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; x0 *= _inv_sigma; dx *= _inv_sigma; y0 *= _inv_sigma; dy *= _inv_sigma; // The Gaussian profile is separable: // val = _norm * exp(-0.5 * (x*x + y*y) // = _norm * exp(-0.5 * x*x) * exp(-0.5 * y*y) tmv::Vector<double> gauss_x(m); It xit = gauss_x.begin(); for (int i=0;i<m;++i,x0+=dx) *xit++ = exp(-0.5 * x0*x0); tmv::Vector<double> gauss_y(n); It yit = gauss_y.begin(); for (int j=0;j<n;++j,y0+=dy) *yit++ = exp(-0.5 * y0*y0); val = _norm * gauss_x ^ gauss_y; } }
void SBKolmogorov::SBKolmogorovImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, int izero, double y0, double dy, int jzero) const { dbg<<"SBKolmogorov fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<", izero = "<<izero<<std::endl; dbg<<"y = "<<y0<<" + j * "<<dy<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillXValueQuadrant(val,x0,dx,izero,y0,dy,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; x0 *= _k0; dx *= _k0; y0 *= _k0; dy *= _k0; for (int j=0;j<n;++j,y0+=dy) { double x = x0; double ysq = y0*y0; It valit = val.col(j).begin(); for (int i=0;i<m;++i,x+=dx) { double r = sqrt(x*x + ysq); *valit++ = _xnorm * _info->xValue(r); } } } }
void SBKolmogorov::SBKolmogorovImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBKolmogorov fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<" + j * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + i * "<<dyx<<" + j * "<<dy<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; x0 *= _k0; dx *= _k0; dxy *= _k0; y0 *= _k0; dy *= _k0; dyx *= _k0; It valit = val.linearView().begin(); for (int j=0;j<n;++j,x0+=dxy,y0+=dy) { double x = x0; double y = y0; for (int i=0;i<m;++i,x+=dx,y+=dyx) { double r = sqrt(x*x + y*y); *valit++ = _xnorm * _info->xValue(r); } } }
void SBTopHat::SBTopHatImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, int izero, double y0, double dy, int jzero) const { dbg<<"SBTopHat fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<", izero = "<<izero<<std::endl; dbg<<"y = "<<y0<<" + j * "<<dy<<", jzero = "<<jzero<<std::endl; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; val.setZero(); // The columns to consider have -r0 <= y < r0 // given that y = y0 + j dy double absdx = std::abs(dx); double absdy = std::abs(dy); int j1 = std::max(0, int(std::ceil(-_r0/absdy - y0/dy))); int j2 = std::min(n, int(std::ceil(_r0/absdy - y0/dy))); y0 += j1 * dy; for (int j=j1;j<j2;++j,y0+=dy) { double ysq = y0*y0; double xmax = std::sqrt(_r0sq - ysq); // Set to _norm all pixels with -xmax <= x < xmax // given that x = x0 + i dx. int i1 = std::max(0, int(std::ceil(-xmax/absdx - x0/dx))); int i2 = std::min(m, int(std::ceil(xmax/absdx - x0/dx))); if (i1 < i2) val.col(j,i1,i2).setAllTo(_norm); } }
void SBBox::SBBoxImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBBox fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<" + j * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + i * "<<dyx<<" + j * "<<dy<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; It valit = val.linearView().begin(); for (int j=0;j<n;++j,x0+=dxy,y0+=dy) { double x = x0; double y = y0; int i=0; // Use the fact that any slice through the box has only one segment that is non-zero. // So start with zeroes until in the box, then _norm, then more zeroes. for (;i<m && (std::abs(x)>_wo2 || std::abs(y)>_ho2); ++i,x+=dx,y+=dyx) *valit++ = 0.; for (;i<m && std::abs(x)<_wo2 && std::abs(y)<_ho2; ++i,x+=dx,y+=dyx) *valit++ = _norm; for (;i<m; ++i,x+=dx,y+=dyx) *valit++ = 0.; } }
void SBBox::SBBoxImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, int izero, double ky0, double dky, int jzero) const { dbg<<"SBBox fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<", izero = "<<izero<<std::endl; dbg<<"ky = "<<ky0<<" + j * "<<dky<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillKValueQuadrant(val,kx0,dkx,izero,ky0,dky,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; kx0 *= _wo2pi; dkx *= _wo2pi; ky0 *= _ho2pi; dky *= _ho2pi; // The Box profile in Fourier space is separable: // val(x,y) = _flux * sinc(x * _width/2pi) * sinc(y * _height/2pi) tmv::Vector<double> sinc_kx(m); It kxit = sinc_kx.begin(); for (int i=0;i<m;++i,kx0+=dkx) *kxit++ = sinc(kx0); tmv::Vector<double> sinc_ky(n); It kyit = sinc_ky.begin(); for (int j=0;j<n;++j,ky0+=dky) *kyit++ = sinc(ky0); val = _flux * sinc_kx ^ sinc_ky; } }
void LVector::kBasis( const tmv::ConstVectorView<double>& kx, const tmv::ConstVectorView<double>& ky, tmv::MatrixView<std::complex<double> > psi_k, int order, double sigma) { assert(ky.size() == kx.size() && psi_k.nrows() == kx.size()); assert(psi_k.ncols()==PQIndex::size(order)); mBasis(kx, ky, 0, psi_k, order, sigma); }
void LVector::basis( const tmv::ConstVectorView<double>& x, const tmv::ConstVectorView<double>& y, tmv::MatrixView<double> psi, int order, double sigma) { assert(y.size() == x.size() && psi.nrows() == x.size()); assert(psi.ncols()==PQIndex::size(order)); mBasis(x, y, 0, psi, order, sigma); }
void SBShapelet::SBShapeletImpl::fillXValue( tmv::MatrixView<double> val, const tmv::Matrix<double>& x, const tmv::Matrix<double>& y) const { dbg<<"order = "<<_bvec.getOrder()<<", sigma = "<<_sigma<<std::endl; xdbg<<"fillXValue with bvec = "<<_bvec<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); tmv::Matrix<double> psi(m*n,_bvec.size()); LVector::basis(x.constLinearView(),y.constLinearView(),psi.view(), _bvec.getOrder(),_sigma); val.linearView() = psi * _bvec.rVector(); }
void SBConvolve::SBConvolveImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBConvolve fillKValue\n"; dbg<<"x = "<<x0<<" + ix * "<<dx<<" + iy * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + ix * "<<dyx<<" + iy * "<<dy<<std::endl; ConstIter pptr = _plist.begin(); assert(pptr != _plist.end()); GetImpl(*pptr)->fillKValue(val,x0,dx,dxy,y0,dy,dyx); if (++pptr != _plist.end()) { tmv::Matrix<std::complex<double> > val2(val.colsize(),val.rowsize()); for (; pptr != _plist.end(); ++pptr) { GetImpl(*pptr)->fillKValue(val2.view(),x0,dx,dxy,y0,dy,dyx); val = ElemProd(val,val2); } } }
void SBAdd::SBAddImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBAdd fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<" + j * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + i * "<<dyx<<" + j * "<<dy<<std::endl; ConstIter pptr = _plist.begin(); assert(pptr != _plist.end()); GetImpl(*pptr)->fillXValue(val,x0,dx,dxy,y0,dy,dyx); if (++pptr != _plist.end()) { tmv::Matrix<double> val2(val.colsize(),val.rowsize()); for (; pptr != _plist.end(); ++pptr) { GetImpl(*pptr)->fillXValue(val2.view(),x0,dx,dxy,y0,dy,dyx); val += val2; } } }
void SBAdd::SBAddImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, double dkxy, double ky0, double dky, double dkyx) const { dbg<<"SBAdd fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<" + j * "<<dkxy<<std::endl; dbg<<"ky = "<<ky0<<" + i * "<<dkyx<<" + j * "<<dky<<std::endl; ConstIter pptr = _plist.begin(); assert(pptr != _plist.end()); GetImpl(*pptr)->fillKValue(val,kx0,dkx,dkxy,ky0,dky,dkyx); if (++pptr != _plist.end()) { tmv::Matrix<std::complex<double> > val2(val.colsize(),val.rowsize()); for (; pptr != _plist.end(); ++pptr) { GetImpl(*pptr)->fillKValue(val2.view(),kx0,dkx,dkxy,ky0,dky,dkyx); val += val2; } } }
void SBConvolve::SBConvolveImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, int izero, double ky0, double dky, int jzero) const { dbg<<"SBConvolve fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<", izero = "<<izero<<std::endl; dbg<<"ky = "<<ky0<<" + j * "<<dky<<", jzero = "<<jzero<<std::endl; ConstIter pptr = _plist.begin(); assert(pptr != _plist.end()); GetImpl(*pptr)->fillKValue(val,kx0,dkx,izero,ky0,dky,jzero); if (++pptr != _plist.end()) { tmv::Matrix<std::complex<double> > val2(val.colsize(),val.rowsize()); for (; pptr != _plist.end(); ++pptr) { GetImpl(*pptr)->fillKValue(val2.view(),kx0,dkx,izero,ky0,dky,jzero); val = ElemProd(val,val2); } } }
void SBShapelet::SBShapeletImpl::fillKValue( tmv::MatrixView<std::complex<double> > val, const tmv::Matrix<double>& kx, const tmv::Matrix<double>& ky) const { dbg<<"order = "<<_bvec.getOrder()<<", sigma = "<<_sigma<<std::endl; xdbg<<"fillKValue with bvec = "<<_bvec<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); tmv::Matrix<std::complex<double> > psi_k(m*n,_bvec.size()); LVector::kBasis(kx.constLinearView(),ky.constLinearView(),psi_k.view(), _bvec.getOrder(),_sigma); // Note: the explicit cast to Vector<complex<double> > shouldn't be necessary. // But not doing so fails for Apple's default BLAS library. It should be a pretty // minimal efficiency difference, so we always do the explicit cast to be safe. val.linearView() = psi_k * tmv::Vector<std::complex<double> >(_bvec.rVector()); }
void SBAutoCorrelate::SBAutoCorrelateImpl::fillKValue( tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, double dkxy, double ky0, double dky, double dkyx) const { dbg<<"SBCorrelate fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<" + j * "<<dkxy<<std::endl; dbg<<"ky = "<<ky0<<" + i * "<<dkyx<<" + j * "<<dky<<std::endl; GetImpl(_adaptee)->fillKValue(val,kx0,dkx,dkxy,ky0,dky,dkyx); val = ElemProd(val,val.conjugate()); }
void SBAutoCorrelate::SBAutoCorrelateImpl::fillKValue( tmv::MatrixView<std::complex<double> > val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBCorrelate fillKValue\n"; dbg<<"x = "<<x0<<" + ix * "<<dx<<" + iy * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + ix * "<<dyx<<" + iy * "<<dy<<std::endl; GetImpl(_adaptee)->fillKValue(val,x0,dx,dxy,y0,dy,dyx); val = ElemProd(val,val.conjugate()); }
void SBTopHat::SBTopHatImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, double dxy, double y0, double dy, double dyx) const { dbg<<"SBTopHat fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<" + j * "<<dxy<<std::endl; dbg<<"y = "<<y0<<" + i * "<<dyx<<" + j * "<<dy<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; val.setZero(); It valit = val.linearView().begin(); for (int j=0;j<n;++j,x0+=dxy,y0+=dy) { double x = x0; double y = y0; int i=0; // Use the fact that any slice through the circle has only one segment that is non-zero. // So start with zeroes until in the circle, then _norm, then more zeroes. // Note: this could be sped up somewhat using the same kind of calculation we did // for the non-sheared fillXValue (the one with izero, jzero), but I didn't // bother. This is probably plenty fast enough for as often as the function is // called (i.e. almost never!) for (;i<m && (x*x+y*y > _r0sq); ++i,x+=dx,y+=dyx) ++valit; for (;i<m && (x*x+y*y < _r0sq); ++i,x+=dx,y+=dyx) *valit++ = _norm; for (;i<m; ++i,x+=dx,y+=dyx) ++valit; } }
void SBExponential::SBExponentialImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, int izero, double ky0, double dky, int jzero) const { dbg<<"SBExponential fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<", izero = "<<izero<<std::endl; dbg<<"ky = "<<ky0<<" + j * "<<dky<<", jzero = "<<jzero<<std::endl; if (izero != 0 || jzero != 0) { xdbg<<"Use Quadrant\n"; fillKValueQuadrant(val,kx0,dkx,izero,ky0,dky,jzero); } else { xdbg<<"Non-Quadrant\n"; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<std::complex<double>,1,tmv::NonConj> It; kx0 *= _r0; dkx *= _r0; ky0 *= _r0; dky *= _r0; for (int j=0;j<n;++j,ky0+=dky) { double kx = kx0; double kysq = ky0*ky0; It valit = val.col(j).begin(); for (int i=0;i<m;++i,kx+=dkx) { double ksq = kx*kx + kysq; if (ksq > _ksq_max) { *valit++ = 0.; } else if (ksq < _ksq_min) { *valit++ = _flux * (1. - 1.5*ksq*(1. - 1.25*ksq)); } else { double temp = 1. + ksq; *valit++ = _flux/(temp*sqrt(temp)); } } } } }
void SBExponential::SBExponentialImpl::fillKValue(tmv::MatrixView<std::complex<double> > val, double kx0, double dkx, double dkxy, double ky0, double dky, double dkyx) const { dbg<<"SBExponential fillKValue\n"; dbg<<"kx = "<<kx0<<" + i * "<<dkx<<" + j * "<<dkxy<<std::endl; dbg<<"ky = "<<ky0<<" + i * "<<dkyx<<" + j * "<<dky<<std::endl; assert(val.stepi() == 1); assert(val.canLinearize()); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<std::complex<double>,1,tmv::NonConj> It; kx0 *= _r0; dkx *= _r0; dkxy *= _r0; ky0 *= _r0; dky *= _r0; dkyx *= _r0; It valit = val.linearView().begin(); for (int j=0;j<n;++j,kx0+=dkxy,ky0+=dky) { double kx = kx0; double ky = ky0; for (int i=0;i<m;++i,kx+=dkx,ky+=dkyx) { double ksq = kx*kx + ky*ky; if (ksq > _ksq_max) { *valit++ = 0.; } else if (ksq < _ksq_min) { *valit++ = _flux * (1. - 1.5*ksq*(1. - 1.25*ksq)); } else { double temp = 1. + ksq; *valit++ = _flux/(temp*sqrt(temp)); } } } }
void LVector::mBasis( const tmv::ConstVectorView<double>& x, const tmv::ConstVectorView<double>& y, const tmv::ConstVectorView<double>* invsig, tmv::MatrixView<T> psi, int order, double sigma) { assert (y.size()==x.size()); assert (psi.nrows()==x.size() && psi.ncols()==PQIndex::size(order)); const int N=order; const int npts_full = x.size(); // It's faster to build the psi matrix in blocks so that more of the matrix stays in // L1 cache. For a (typical) 256 KB L2 cache size, this corresponds to 8 columns in the // cache, which is pretty good, since we are usually working on 4 columns at a time, // plus either X and Y or 3 Lq vectors. const int BLOCKING_FACTOR=4096; const int max_npts = std::max(BLOCKING_FACTOR,npts_full); tmv::DiagMatrix<double> Rsq_full(max_npts); tmv::Matrix<double> A_full(max_npts,2); tmv::Matrix<double> tmp_full(max_npts,2); tmv::DiagMatrix<double> Lmq_full(max_npts); tmv::DiagMatrix<double> Lmqm1_full(max_npts); tmv::DiagMatrix<double> Lmqm2_full(max_npts); for (int ilo=0; ilo<npts_full; ilo+=BLOCKING_FACTOR) { const int ihi = std::min(npts_full, ilo + BLOCKING_FACTOR); const int npts = ihi-ilo; // Cast arguments as diagonal matrices so we can access // vectorized element-by-element multiplication tmv::ConstDiagMatrixView<double> X = DiagMatrixViewOf(x.subVector(ilo,ihi)); tmv::ConstDiagMatrixView<double> Y = DiagMatrixViewOf(y.subVector(ilo,ihi)); // Get the appropriate portion of our temporary matrices. tmv::DiagMatrixView<double> Rsq = Rsq_full.subDiagMatrix(0,npts); tmv::MatrixView<double> A = A_full.rowRange(0,npts); tmv::MatrixView<double> tmp = tmp_full.rowRange(0,npts); // We need rsq values twice, so store them here. Rsq = X*X; Rsq += Y*Y; // This matrix will keep track of real & imag parts // of prefactor * exp(-r^2/2) (x+iy)^m / sqrt(m!) // Build the Gaussian factor for (int i=0; i<npts; i++) A.ref(i,0) = std::exp(-0.5*Rsq(i)); mBasisHelper<T>::applyPrefactor(A.col(0),sigma); A.col(1).setZero(); // Put 1/sigma factor into every point if doing a design matrix: if (invsig) A.col(0) *= tmv::DiagMatrixViewOf(invsig->subVector(ilo,ihi)); // Assign the m=0 column first: psi.col( PQIndex(0,0).rIndex(), ilo,ihi ) = A.col(0); // Then ascend m's at q=0: for (int m=1; m<=N; m++) { int rIndex = PQIndex(m,0).rIndex(); // Multiply by (X+iY)/sqrt(m), including a factor 2 first time through tmp = Y * A; A = X * A; A.col(0) += tmp.col(1); A.col(1) -= tmp.col(0); A *= m==1 ? 2. : 1./sqrtn(m); psi.subMatrix(ilo,ihi,rIndex,rIndex+2) = mBasisHelper<T>::Asign(m%4) * A; } // Make three DiagMatrix to hold Lmq's during recurrence calculations boost::shared_ptr<tmv::DiagMatrixView<double> > Lmq( new tmv::DiagMatrixView<double>(Lmq_full.subDiagMatrix(0,npts))); boost::shared_ptr<tmv::DiagMatrixView<double> > Lmqm1( new tmv::DiagMatrixView<double>(Lmqm1_full.subDiagMatrix(0,npts))); boost::shared_ptr<tmv::DiagMatrixView<double> > Lmqm2( new tmv::DiagMatrixView<double>(Lmqm2_full.subDiagMatrix(0,npts))); for (int m=0; m<=N; m++) { PQIndex pq(m,0); int iQ0 = pq.rIndex(); // Go to q=1: pq.incN(); if (pq.pastOrder(N)) continue; { // q == 1 const int p = pq.getP(); const int q = pq.getQ(); const int iQ = pq.rIndex(); Lmqm1->setAllTo(1.); // This is Lm0. *Lmq = Rsq - (p+q-1.); *Lmq *= mBasisHelper<T>::Lsign(1.) / (sqrtn(p)*sqrtn(q)); if (m==0) { psi.col(iQ,ilo,ihi) = (*Lmq) * psi.col(iQ0,ilo,ihi); } else { psi.subMatrix(ilo,ihi,iQ,iQ+2) = (*Lmq) * psi.subMatrix(ilo,ihi,iQ0,iQ0+2); } } // do q=2,... for (pq.incN(); !pq.pastOrder(N); pq.incN()) { const int p = pq.getP(); const int q = pq.getQ(); const int iQ = pq.rIndex(); // cycle the Lmq vectors // Lmqm2 <- Lmqm1 // Lmqm1 <- Lmq // Lmq <- Lmqm2 Lmqm2.swap(Lmqm1); Lmqm1.swap(Lmq); double invsqrtpq = 1./sqrtn(p)/sqrtn(q); *Lmq = Rsq - (p+q-1.); *Lmq *= mBasisHelper<T>::Lsign(invsqrtpq) * *Lmqm1; *Lmq -= (sqrtn(p-1)*sqrtn(q-1)*invsqrtpq) * (*Lmqm2); if (m==0) { psi.col(iQ,ilo,ihi) = (*Lmq) * psi.col(iQ0,ilo,ihi); } else { psi.subMatrix(ilo,ihi,iQ,iQ+2) = (*Lmq) * psi.subMatrix(ilo,ihi,iQ0,iQ0+2); } } } } }
void SBBox::SBBoxImpl::fillXValue(tmv::MatrixView<double> val, double x0, double dx, int izero, double y0, double dy, int jzero) const { dbg<<"SBBox fillXValue\n"; dbg<<"x = "<<x0<<" + i * "<<dx<<", izero = "<<izero<<std::endl; dbg<<"y = "<<y0<<" + j * "<<dy<<", jzero = "<<jzero<<std::endl; assert(val.stepi() == 1); const int m = val.colsize(); const int n = val.rowsize(); typedef tmv::VIt<double,1,tmv::NonConj> It; // It will be useful to do everything in units of dx,dy x0 /= dx; double wo2 = _wo2 / std::abs(dx); y0 /= dy; double ho2 = _ho2 / std::abs(dy); xdbg<<"x0,y0 -> "<<x0<<','<<y0<<std::endl; xdbg<<"width,height -> "<<wo2*2.<<','<<ho2*2.<<std::endl; // Start by setting everything to zero val.setZero(); // Then fill the interior with _norm: // Fill pixels where: // x0 + ix >= -width/2 // x0 + ix < width/2 // y0 + iy >= -width/2 // y0 + iy < width/2 int ix1 = std::max(0, int(std::ceil(-wo2 - x0))); int ix2 = std::min(m, int(std::ceil(wo2 - x0))); int iy1 = std::max(0, int(std::ceil(-ho2 - y0))); int iy2 = std::min(n, int(std::ceil(ho2 - y0))); if (ix1 < ix2 && iy1 < iy2) val.subMatrix(ix1,ix2,iy1,iy2).setAllTo(_norm); #if 0 // We used to implement this by making the pixels that cross the edge have a // fractional flux value appropriate for the fraction of the box that goes through // each pixel. However, this isn't actually correct. SBProfile objects are always // rendered as the local surface brightness at the center of the pixel. To get // the right flux, you need to convolve by a Pixel. So if someone renders a Box // without convolving by a pixel, it is inconsistent to do this differently than we // do all the other SBProfile types. However, since it was an involved calculation // and someone might actually care to resurrect it in a different guise at some point, // I'm leaving it here, just commented out. // We need to make sure the pixels where the edges of the box fall only get // a fraction of the flux. // // We divide up the range into 3 sections in x: // left of the box where val = 0 // in the box where val = _norm // right of the box where val = 0 again // // ... and 3 sections in y: // below the box where val = 0 // in the box where val = _norm // above the box where val = 0 again // // Furthermore, we have to calculate the correct values for the pixels on the border. int ix_left, ix_right, iy_bottom, iy_top; double x_left, x_right, y_bottom, y_top; // Find the x edges: double tmp = 0.5*width + 0.5; ix_left = int(-tmp-x0+1); ix_right = int(tmp-x0); // If the box goes off the image, it's ok, but it will cause us problems // later on if we don't change it. Just use ix_left = 0. if (ix_left < 0) { ix_left = 0; x_left = 1.; } // If the whole box is off the image, just zero and return. else if (ix_left >= m) { val.setZero(); return; } // Normal case: calculate the fractional flux in the edge else x_left = tmp+x0+ix_left; // Now the right side. if (ix_right >= m) { ix_right = m-1; x_right = 1.; } else if (ix_right < 0) { val.setZero(); return; } else x_right = tmp-x0-ix_right; xdbg<<"ix_left = "<<ix_left<<" with partial flux "<<x_left<<std::endl; xdbg<<"ix_right = "<<ix_right<<" with partial flux "<<x_right<<std::endl; // Repeat for y values tmp = 0.5*height + 0.5; iy_bottom = int(-tmp-y0+1); iy_top = int(tmp-y0); if (iy_bottom < 0) { iy_bottom = 0; y_bottom = 1.; } else if (iy_bottom >= n) { val.setZero(); return; } else y_bottom = tmp+y0+iy_bottom; if (iy_top >= n) { iy_top = n-1; y_top = 1.; } else if (iy_top < 0) { val.setZero(); return; } else y_top = tmp-y0-iy_top; xdbg<<"iy_bottom = "<<iy_bottom<<" with partial flux "<<y_bottom<<std::endl; xdbg<<"iy_top = "<<iy_top<<" with partial flux "<<y_top<<std::endl; xdbg<<"m,n = "<<m<<','<<n<<std::endl; // Now we need to fill the matrix with the appropriate values in each section. // Start with the zeros: if (0 < ix_left) val.subMatrix(0,ix_left,iy_bottom,iy_top+1).setZero(); if (ix_right+1 < m) val.subMatrix(ix_right+1,m,iy_bottom,iy_top+1).setZero(); if (0 < iy_bottom) val.colRange(0,iy_bottom).setZero(); if (iy_top+1 < n) val.colRange(iy_top+1,n).setZero(); // Then the interior: if (ix_left+1 < ix_right && iy_bottom+1 < iy_top) val.subMatrix(ix_left+1,ix_right,iy_bottom+1,iy_top).setAllTo(_norm); // And now the edges: if (ix_left+1 < ix_right) { val.col(iy_bottom,ix_left+1,ix_right).setAllTo(y_bottom * _norm); val.col(iy_top,ix_left+1,ix_right).setAllTo(y_top * _norm); } if (iy_bottom+1 < iy_top) { val.row(ix_left,iy_bottom+1,iy_top).setAllTo(x_left * _norm); val.row(ix_right,iy_bottom+1,iy_top).setAllTo(x_right * _norm); } // Finally the corners val(ix_left,iy_bottom) = x_left * y_bottom * _norm; val(ix_right,iy_bottom) = x_right * y_bottom * _norm; val(ix_left,iy_top) = x_left * y_top * _norm; val(ix_right,iy_top) = x_right * y_top * _norm; #endif }