| 129 | } |
| 130 | |
| 131 | std::string parallel_lines::data_string() { |
| 132 | // calculate data for jitter |
| 133 | std::vector<double> X_min; |
| 134 | std::vector<double> X_max; |
| 135 | std::vector<double> X_range; |
| 136 | constexpr double expand_factor = 0.03; |
| 137 | std::vector<double> expanded_X_min; |
| 138 | std::vector<double> expanded_X_max; |
| 139 | std::vector<double> expanded_X_range; |
| 140 | for (size_t i = 0; i < data_.size(); ++i) { |
| 141 | auto [min_it, max_it] = |
| 142 | std::minmax_element(data_[i].begin(), data_[i].end()); |
| 143 | X_min.emplace_back(*min_it); |
| 144 | X_max.emplace_back(*max_it); |
| 145 | X_range.emplace_back(X_max.back() - X_min.back()); |
| 146 | expanded_X_min.emplace_back(*min_it - |
| 147 | expand_factor * X_range.back()); |
| 148 | expanded_X_max.emplace_back(*max_it + |
| 149 | expand_factor * X_range.back()); |
| 150 | expanded_X_range.emplace_back(expanded_X_max.back() - |
| 151 | expanded_X_min.back()); |
| 152 | } |
| 153 | |
| 154 | auto jitter = [&](double y, size_t dimension) { |
| 155 | double y2 = |
| 156 | y + randn(0, (X_max[dimension] - X_min[dimension]) / 100); |
| 157 | // reflect |
| 158 | if (y2 < X_min[dimension]) { |
| 159 | y2 += 2 * (X_min[dimension] - y2); |
| 160 | } else if (y2 > X_max[dimension]) { |
| 161 | y2 -= 2 * (y2 - X_max[dimension]); |
| 162 | } |
| 163 | return y2; |
| 164 | }; |
| 165 | |
| 166 | auto normalize = [&](double y, size_t dimension) { |
| 167 | return (y - expanded_X_min[dimension]) / |
| 168 | expanded_X_range[dimension]; |
| 169 | }; |
| 170 | |
| 171 | const bool color_is_variable = !line_colors_.empty(); |
| 172 | std::stringstream ss; |
| 173 | ss.precision(10); |
| 174 | ss << std::fixed; |
| 175 | // for each point |
| 176 | for (size_t i = 0; i < data_[0].size(); ++i) { |
| 177 | // for each dimension |
| 178 | for (size_t dimension = 0; dimension < data_.size(); ++dimension) { |
| 179 | ss << " " << dimension + 1 << " "; |
| 180 | if (!jitter_) { |
| 181 | ss << normalize(data_[dimension][i], dimension) << " "; |
| 182 | } else { |
| 183 | ss << normalize(jitter(data_[dimension][i], dimension), |
| 184 | dimension) |
| 185 | << " "; |
| 186 | } |
| 187 | if (color_is_variable) { |
| 188 | ss << line_colors_[i] << " "; |