33#ifndef _USE_MATH_DEFINES
34#define _USE_MATH_DEFINES
64 return gcd(iB, iA % iB);
75 for (qint32 i = 0; i < n; ++i) {
89 int t_iNumOfCombination =
static_cast<int>(n * (n - 1) * 0.5);
91 return t_iNumOfCombination;
100 const double a = 0.5 * dof;
101 auto upperTail = [a](
double chi2) {
102 const double x = 0.5 * chi2;
105 for (
int n = 1; n < 100000 && term > 1e-17 * sum; ++n) {
109 return 1.0 - sum * std::exp(a * std::log(x) - x - std::lgamma(a + 1.0));
112 double hi = dof + 10.0 * std::sqrt(2.0 * dof) + 50.0;
113 while (upperTail(hi) > p)
115 for (
int i = 0; i < 200 && hi - lo > 1e-14 * hi; ++i) {
116 const double mid = 0.5 * (lo + hi);
117 (upperTail(mid) > p ? lo : hi) = mid;
119 return 0.5 * (lo + hi);
125 const RowVectorXf& times,
126 const QPair<float, float>& baseline,
129 MatrixXd data_out = data;
130 QStringList valid_modes;
131 valid_modes <<
"logratio" <<
"ratio" <<
"zscore" <<
"mean" <<
"percent";
132 if (!valid_modes.contains(mode)) {
133 qWarning().noquote() <<
"[Numerics::rescale] Mode" << mode <<
"is not supported. Supported modes are:" << valid_modes <<
"Returning input data.";
137 qInfo().noquote() << QString(
"[Numerics::rescale] Applying baseline correction ... (mode: %1)").arg(mode);
140 qint32 imax = times.size();
142 if (baseline.second == baseline.first) {
145 float bmin = baseline.first;
146 for (qint32 i = 0; i < times.size(); ++i) {
147 if (times[i] >= bmin) {
154 float bmax = baseline.second;
156 if (baseline.second == baseline.first) {
160 for (qint32 i = times.size() - 1; i >= 0; --i) {
161 if (times[i] <= bmax) {
168 qWarning() <<
"[Numerics::rescale] imax < imin. Returning input data.";
172 VectorXd mean = data_out.block(0, imin, data_out.rows(), imax - imin).rowwise().mean();
173 if (mode.compare(
"mean") == 0) {
174 data_out -= mean.rowwise().replicate(data.cols());
175 }
else if (mode.compare(
"logratio") == 0) {
176 for (qint32 i = 0; i < data_out.rows(); ++i)
177 for (qint32 j = 0; j < data_out.cols(); ++j)
178 data_out(i, j) = log10(data_out(i, j) / mean[i]);
179 }
else if (mode.compare(
"ratio") == 0) {
180 data_out = data_out.cwiseQuotient(mean.rowwise().replicate(data_out.cols()));
181 }
else if (mode.compare(
"zscore") == 0) {
182 MatrixXd std_mat = data.block(0, imin, data.rows(), imax - imin) - mean.rowwise().replicate(imax - imin);
183 std_mat = std_mat.cwiseProduct(std_mat);
184 VectorXd std_v = std_mat.rowwise().mean();
185 for (qint32 i = 0; i < std_v.size(); ++i)
186 std_v[i] = sqrt(std_v[i] /
static_cast<float>(imax - imin));
188 data_out -= mean.rowwise().replicate(data_out.cols());
189 data_out = data_out.cwiseQuotient(std_v.rowwise().replicate(data_out.cols()));
190 }
else if (mode.compare(
"percent") == 0) {
191 data_out -= mean.rowwise().replicate(data_out.cols());
192 data_out = data_out.cwiseQuotient(mean.rowwise().replicate(data_out.cols()));
201 const RowVectorXf& times,
202 const std::pair<float, float>& baseline,
203 const std::string& mode)
205 MatrixXd data_out = data;
206 std::vector<std::string> valid_modes{
"logratio",
"ratio",
"zscore",
"mean",
"percent"};
207 if (std::find(valid_modes.begin(), valid_modes.end(), mode) == valid_modes.end()) {
208 qWarning().noquote() <<
"[Numerics::rescale] Mode" << mode.c_str() <<
"is not supported. Supported modes are:";
209 for (
auto& m : valid_modes) {
210 std::cout << m <<
" ";
213 <<
"Returning input data.\n";
217 qInfo().noquote() << QString(
"[Numerics::rescale] Applying baseline correction ... (mode: %1)").arg(mode.c_str());
220 qint32 imax = times.size();
222 if (baseline.second == baseline.first) {
225 float bmin = baseline.first;
226 for (qint32 i = 0; i < times.size(); ++i) {
227 if (times[i] >= bmin) {
234 float bmax = baseline.second;
236 if (baseline.second == baseline.first) {
240 for (qint32 i = times.size() - 1; i >= 0; --i) {
241 if (times[i] <= bmax) {
248 qWarning() <<
"[Numerics::rescale] imax < imin. Returning input data.";
252 VectorXd mean = data_out.block(0, imin, data_out.rows(), imax - imin).rowwise().mean();
253 if (mode.compare(
"mean") == 0) {
254 data_out -= mean.rowwise().replicate(data.cols());
255 }
else if (mode.compare(
"logratio") == 0) {
256 for (qint32 i = 0; i < data_out.rows(); ++i)
257 for (qint32 j = 0; j < data_out.cols(); ++j)
258 data_out(i, j) = log10(data_out(i, j) / mean[i]);
259 }
else if (mode.compare(
"ratio") == 0) {
260 data_out = data_out.cwiseQuotient(mean.rowwise().replicate(data_out.cols()));
261 }
else if (mode.compare(
"zscore") == 0) {
262 MatrixXd std_mat = data.block(0, imin, data.rows(), imax - imin) - mean.rowwise().replicate(imax - imin);
263 std_mat = std_mat.cwiseProduct(std_mat);
264 VectorXd std_v = std_mat.rowwise().mean();
265 for (qint32 i = 0; i < std_v.size(); ++i)
266 std_v[i] = sqrt(std_v[i] /
static_cast<float>(imax - imin));
268 data_out -= mean.rowwise().replicate(data_out.cols());
269 data_out = data_out.cwiseQuotient(std_v.rowwise().replicate(data_out.cols()));
270 }
else if (mode.compare(
"percent") == 0) {
271 data_out -= mean.rowwise().replicate(data_out.cols());
272 data_out = data_out.cwiseQuotient(mean.rowwise().replicate(data_out.cols()));
General numerical helpers: GCD, log2, histogram binning, baseline rescaling, sparsity tests.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
static int gcd(int iA, int iB)
static double chi2Isf(double p, int dof)
static bool issparse(Eigen::VectorXd &v)
static Eigen::MatrixXd rescale(const Eigen::MatrixXd &data, const Eigen::RowVectorXf ×, const QPair< float, float > &baseline, QString mode)
static int nchoose2(int n)