| 122 | } |
| 123 | |
| 124 | void Painter2DPeak::paint(QPainter* painter, Plot2DCanvas* canvas, int layer_index) |
| 125 | { |
| 126 | // renaming some values for readability |
| 127 | const auto& peak_map = *layer_->getPeakData(); |
| 128 | |
| 129 | // skip empty peak maps |
| 130 | if (peak_map.empty()) |
| 131 | { |
| 132 | return; |
| 133 | } |
| 134 | |
| 135 | const auto [rt_min, rt_max] = canvas->visible_area_.getAreaUnit().RangeRT::getNonEmptyRange(); |
| 136 | const auto [mz_min, mz_max] = canvas->visible_area_.getAreaUnit().RangeMZ::getNonEmptyRange(); |
| 137 | const auto [im_min, im_max] = canvas->visible_area_.getAreaUnit().RangeMobility::getNonEmptyRange(); |
| 138 | |
| 139 | //----------------------------------------------------------------------------------------------- |
| 140 | // Determine number of shown scans (MS1) |
| 141 | std::vector<Size> scan_indices; // list of visible RT/IM scans in MS1 with at least 2 points |
| 142 | const auto rt_end = peak_map.RTEnd(rt_max); |
| 143 | for (auto it = peak_map.RTBegin(rt_min); it != rt_end; ++it) |
| 144 | { |
| 145 | if (it->getMSLevel() == 1 && it->size() > 1 && Math::contains(it->getDriftTime(), im_min, im_max)) |
| 146 | { |
| 147 | scan_indices.push_back(std::distance(peak_map.begin(), it)); |
| 148 | } |
| 149 | } |
| 150 | Size n_ms1_scans = scan_indices.size(); |
| 151 | |
| 152 | if (n_ms1_scans > 0) |
| 153 | { |
| 154 | // sample #of points at 3 scan locations (25%, 50%, 75%) |
| 155 | // and take the median value |
| 156 | Size n_peaks_in_scan(0); |
| 157 | { |
| 158 | static constexpr std::array<double, 3> quantiles = {0.25, 0.50, 0.75}; |
| 159 | std::array<Size, quantiles.size()> n_s; |
| 160 | for (Size i = 0; i < quantiles.size(); ++i) |
| 161 | { |
| 162 | const auto& spec = peak_map[scan_indices[n_ms1_scans * quantiles[i]]]; |
| 163 | if (!spec.isSorted()) |
| 164 | throw Exception::BaseException(); |
| 165 | n_s[i] = std::distance(spec.MZBegin(mz_min), spec.MZEnd(mz_max)); |
| 166 | } |
| 167 | std::sort(n_s.begin(), n_s.end()); |
| 168 | n_peaks_in_scan = n_s[1]; // median |
| 169 | } |
| 170 | |
| 171 | Size rt_pixel_count, mz_pixel_count; |
| 172 | { // obtain number of pixels in RT/IM and MZ dimension |
| 173 | auto tmp = canvas->getPixelRange().getAreaUnit(); |
| 174 | rt_pixel_count = tmp.RangeRT::isEmpty() ? tmp.getMaxMobility() : tmp.getMaxRT(); |
| 175 | mz_pixel_count = tmp.getMaxMZ(); |
| 176 | } |
| 177 | double ratio_data2pixel_rt = n_ms1_scans / (double)rt_pixel_count; |
| 178 | double ratio_data2pixel_mz = n_peaks_in_scan / (double)mz_pixel_count; |
| 179 | |
| 180 | // minimum fraction of image expected to be filled with data |
| 181 | // if not reached, we upscale point size |
nothing calls this directly
no test coverage detected