6#include <unsupported/Eigen/FFT>
8#include <tula/algorithm/mlinterp/mlinterp.hpp>
9#include <tula/algorithm/ei_stats.h>
15template <
typename Derived>
17 Eigen::Index n_pts = in.size();
25 int w_mid = (w - 1)/2;
28 for (Eigen::Index i=0; i<n_pts; i++) {
30 for (
int j=0; j<w; j++) {
31 int add_index = i + j - w_mid;
36 else if (add_index > n_pts-1) {
46 return static_cast<T *
>(
nullptr);
49template <
typename Derived>
50using const_ref =
typename Eigen::internal::ref_selector<Derived>::type;
53template <
typename Derived>
54using ref =
typename Eigen::internal::ref_selector<Derived>::non_const_type;
58template <
typename Derived>
60 : std::is_base_of<Eigen::PlainObjectBase<std::decay_t<Derived>>,
61 std::decay_t<Derived>> {};
66 template <
typename T,
typename... Args>
67 decltype(
auto)
operator()(T &&in, Args &&... args) {
68 if constexpr (std::is_lvalue_reference<T>::value ||
72 return m_func(std::forward<T>(in),
73 std::forward<
decltype(args)>(args)...);
79 in =
m_func(std::forward<T>(in),
80 std::forward<
decltype(args)>(args)...);
81 return std::forward<T>(in);
90template <
typename _Scalar>
91class Interval :
public Eigen::Array<_Scalar, 2, 1> {
94 using Base = Eigen::Array<_Scalar, 2, 1>;
95 inline static const Scalar inf = std::numeric_limits<Scalar>::infinity();
98 this->operator[](0) = -
inf;
99 this->operator[](1) =
inf;
102 if (interval.size() == 0)
104 if (interval.size() == 2) {
105 auto it = interval.begin();
106 this->operator[](0) = *it;
108 this->operator[](1) = *it;
111 throw std::invalid_argument(
112 "empty initalize_list or {left, right} is required");
115 template <
typename OtherDerived>
118 template <
typename OtherDerived>
120 this->Base::operator=(other);
131using FreqStat = std::tuple<Eigen::Index, Eigen::Index, double>;
134Eigen::VectorXd
freq(Eigen::Index npts, Eigen::Index nfreqs,
double dfreq);
141inline decltype(
auto)
hann(Eigen::Index npts) {
147 return (0.5 - 0.5 * Eigen::ArrayXd::LinSpaced(npts, 0, 2.0 *
pi / npts * (npts - 1)).cos()).matrix() / 1.5;
151template <Window win=Hanning,
typename DerivedA,
typename DerivedB,
typename DerivedC>
153 Eigen::DenseBase<DerivedB> &
psd, Eigen::DenseBase<DerivedC> *freqs,
159 auto [npts, nfreqs, dfreq] =
stat;
162 Eigen::FFT<double> fft;
163 fft.SetFlag(Eigen::FFT<double>::HalfSpectrum);
164 fft.SetFlag(Eigen::FFT<double>::Unscaled);
165 Eigen::VectorXcd freqdata;
168 if constexpr (win ==
Hanning) {
170 Eigen::VectorXd scns = scan.block(0,0,npts,1);
171 fft.fwd(freqdata, scns.cwiseProduct(
176 fft.fwd(freqdata, scan.head(npts));
180 psd = freqdata.cwiseAbs2() / dfreq / npts/ fsmp;
183 psd.segment(1, nfreqs - 2) *= 2.;
185 Eigen::VectorXd smoothed_psd(
psd.size());
187 psd = std::move(smoothed_psd);
198template <Window win=Hanning,
typename DerivedA,
typename DerivedB,
typename DerivedC>
200 Eigen::DenseBase<DerivedB> &_psds,
201 Eigen::DenseBase<DerivedC> *freqs,
double fsmp, Eigen::Index det) {
206 Eigen::Index nscans = ptcs.size();
207 Eigen::Matrix<Eigen::Index,Eigen::Dynamic,1> scanlengths;
209 scanlengths.resize(nscans);
210 for(Eigen::Index j=0; j<nscans; j++) {
211 scanlengths(j) = ptcs[j].scans.data.rows();
215 Eigen::Index len = tula::alg::median(scanlengths);
219 auto [npts, nfreqs, dfreq] =
stat;
223 psds.resize(nfreqs, nscans);
226 Eigen::VectorXd tfreqs, tpsd;
228 Eigen::Matrix<Eigen::Index, Eigen::Dynamic,1> td(1);
231 for (Eigen::Index i=0; i<nscans; ++i) {
232 internal::psd<win>(ptcs[i].scans.data.block(0,det,scanlengths(i),1), tpsd,
238 mlinterp::interp(td.data(), nfreqs,
239 tpsd.data(),
psds.data() + i * nfreqs,
240 tfreqs.data(),_freqs.data());
245 freqs->operator=(_freqs);
252 return (
psd / 2.).cwiseSqrt();
258template <
typename tc_t,
typename DerivedA,
typename DerivedB>
260 std::vector<tc_t> &ptcs,
261 Eigen::DenseBase<DerivedA> &sensitivities,
262 Eigen::DenseBase<DerivedB> &noisefluxes,
266 Eigen::MatrixXd tpsds;
267 auto [npts, nfreqs, dfreq] = internal::psds<internal::Hanning>(
271 noisefluxes = (tpsds * dfreq).colwise().sum().cwiseSqrt();
272 auto meannoise = noisefluxes.mean();
279 auto i0 =
static_cast<Eigen::Index
>(freqrange.left() / dfreq);
280 auto i1 =
static_cast<Eigen::Index
>(freqrange.right() / dfreq);
282 auto nf = i1 + 1 - i0;
284 sens.block(i0, 0, nf, ptcs.size()).colwise().sum() / nf;
Definition sensitivity.h:91
Eigen::Array< _Scalar, 2, 1 > Base
Definition sensitivity.h:94
Interval(const Eigen::ArrayBase< OtherDerived > &other)
Definition sensitivity.h:116
_Scalar Scalar
Definition sensitivity.h:93
Interval(std::initializer_list< Scalar > interval)
Definition sensitivity.h:101
Interval & operator=(const Eigen::ArrayBase< OtherDerived > &other)
Definition sensitivity.h:119
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar & left()
Definition sensitivity.h:124
Interval()
Definition sensitivity.h:97
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar & right()
Definition sensitivity.h:126
static const Scalar inf
Definition sensitivity.h:95
constexpr auto pi
Definition constants.h:6
Definition sensitivity.h:13
Window
Definition sensitivity.h:136
@ NoWindow
Definition sensitivity.h:137
@ Hanning
Definition sensitivity.h:138
T * ei_nullptr()
Definition sensitivity.h:45
Eigen::VectorXd freq(Eigen::Index npts, Eigen::Index nfreqs, double dfreq)
Definition sensitivity.cpp:20
std::tuple< Eigen::Index, Eigen::Index, double > FreqStat
Definition sensitivity.h:131
void smooth_edge_truncate(Eigen::DenseBase< Derived > &in, Eigen::DenseBase< Derived > &out, int w)
Definition sensitivity.h:16
FreqStat stat(Eigen::Index scanlength, double fsmp)
Definition sensitivity.cpp:8
FreqStat psds(const std::vector< DerivedA > &ptcs, Eigen::DenseBase< DerivedB > &_psds, Eigen::DenseBase< DerivedC > *freqs, double fsmp, Eigen::Index det)
Definition sensitivity.h:199
typename Eigen::internal::ref_selector< Derived >::non_const_type ref
Definition sensitivity.h:54
decltype(auto) hann(Eigen::Index npts)
Definition sensitivity.h:141
FreqStat psd(const Eigen::DenseBase< DerivedA > &_scan, Eigen::DenseBase< DerivedB > &psd, Eigen::DenseBase< DerivedC > *freqs, double fsmp)
Definition sensitivity.h:152
auto psd2sen
Definition sensitivity.h:251
typename Eigen::internal::ref_selector< Derived >::type const_ref
Definition sensitivity.h:50
void calc_sensitivity(std::vector< tc_t > &ptcs, Eigen::DenseBase< DerivedA > &sensitivities, Eigen::DenseBase< DerivedB > &noisefluxes, double fsmp, Eigen::Index det, internal::Interval< double > freqrange={3., 5.})
Definition sensitivity.h:259
Definition sensitivity.h:63
const UnaryOp & m_func
Definition sensitivity.h:86
MoveEnabledUnaryOp(const UnaryOp &func=UnaryOp())
Definition sensitivity.h:64
Definition sensitivity.h:61