hits.cxx
Go to the documentation of this file.
1 #include <gtk/gtk.h>
2 #include <vector>
3 #include <algorithm>
4 #include <stdint.h>
5 #include "event.h"
6 #include "drawing.h"
7 #include "geo.h"
8 #include "status.h"
9 
10 extern std::vector<noeevent> theevents;
11 extern int gevi;
12 extern int pixx, pixy;
13 extern int active_plane, active_cell;
14 
15 static bool by_charge(const hit & a, const hit & b)
16 {
17  return a.adc < b.adc;
18 }
19 
20 __attribute__((unused)) static bool by_time(const hit & a, const hit & b)
21 {
22  return a.tdc < b.tdc;
23 }
24 
25 // Given a hit energy, set red, green and blue to the color we want to display
26 // for the hit. If "active" is true, set a brighter color. This is intended
27 // for when the user has moused over the cell.
28 static void colorhit(const int32_t adc, float & red, float & green, float & blue,
29  const bool active)
30 {
31  // Oh so hacky!
32  const float graycut = 60;
33  const float nextcut = 120;
34  if(adc < graycut) red = green = blue = 0.2 + 0.3*adc/graycut;
35  else if(adc < nextcut)
36  blue = 0.5 + 0.5*(adc-graycut)/(nextcut-graycut),
37  red = 0.5 - 0.5*(adc-graycut)/(nextcut-graycut),
38  green = 0.5 - 0.5*(adc-graycut)/(nextcut-graycut);
39  else if(adc < 600) blue = 1, red = green = 0;
40  else if(adc < 800) blue = 1-(adc-600)/200.0,
41  green = (adc-600)/200.0,
42  red = 0;
43  else if(adc < 1200) green = 1, red = blue = 0;
44  else if(adc < 1400) green = 1-(adc-1200)/200.0,
45  red = (adc-1200)/200.0,
46  blue = 0;
47  else red = 1, green = blue = 0;
48 
49  // Brighten this hit while trying to retain some of its original color, but
50  // just make it white if that is what it takes to make a difference.
51  if(active){
52  const float goal = 1.3;
53  const float left = 3 - red - blue - green;
54  if(left < goal){
55  red = blue = green = 1;
56  }
57  else{
58  red += goal*(1 - red)/left;
59  blue += goal*(1 - blue)/left;
60  green += goal*(1 - green)/left;
61  }
62  }
63 }
64 
65 // Draw a single hit to the screen, taking into account whether it is the
66 // "active" hit (i.e. being moused over right now).
67 void draw_hit(cairo_t * cr, const hit & thishit, GtkWidget ** edarea)
68 {
69  const noe_view_t V = thishit.plane%2 == 1?kX:kY;
70 
71  // Get position of upper left corner. If the zoom carries this hit entirely
72  // out of the view in screen y, don't waste cycles displaying it.
73  const int screenx = det_to_screen_x(thishit.plane);
74  if(screenx+pixx < 0) return;
75  if(screenx > edarea[V]->allocation.width) return;
76 
77  const int screeny = det_to_screen_y(thishit.plane, thishit.cell);
78  if(screeny+pixy < 0) return;
79  if(screeny > edarea[V]->allocation.height) return;
80 
81  float red, green, blue;
82 
83  colorhit(thishit.adc, red, green, blue,
84  thishit.plane == active_plane && thishit.cell == active_cell);
85 
86  cairo_set_source_rgb(cr, red, green, blue);
87 
88  // If we're representing cells with a very small number of pixels,
89  // draw all the way across to the next plane in the view to be easier
90  // to look at. If cells are visually large, make them closer to the
91  // actual size of the scintillator.
92  // XXX how about a yexpand to show the scintillator size in y?
93  // XXX are tracks correctly aligned with hits in both expanded and unexpanded
94  // styles? (Probably not!)
95  const bool xexpand = pixx <= 3;
96  const int epixx = xexpand?pixx:scintpix_from_pixx(pixx);
97 
98  // This is the only part of drawing an event that takes any time
99  // I have measured drawing a line to be twice as fast as drawing a
100  // rectangle of width 1, so it is totally worth it to have a special
101  // case. This really helps with drawing big events.
102  if(pixy == 1){
103  cairo_move_to(cr, screenx, screeny+0.5);
104  cairo_line_to(cr, screenx+epixx, screeny+0.5);
105  cairo_stroke(cr);
106  }
107  // This is a smaller gain, but it is definitely faster by about 10%.
108  else if(pixy == 2){
109  cairo_move_to(cr, screenx, screeny+0.5);
110  cairo_line_to(cr, screenx+epixx, screeny+0.5);
111  cairo_move_to(cr, screenx, screeny+1.5);
112  cairo_line_to(cr, screenx+epixx, screeny+1.5);
113  cairo_stroke(cr);
114  }
115  else{
116  cairo_rectangle(cr, screenx+0.5, screeny+0.5,
117  epixx-1, pixy-1);
118  cairo_fill(cr);
119  }
120 }
121 
122 
123 // Draw all the hits in the event that we need to draw, depending on
124 // whether we are animating or have been exposed, etc.
125 void draw_hits(cairo_t ** cr, const DRAWPARS * const drawpars, GtkWidget ** edarea)
126 {
127  if(theevents[gevi].hits.empty()) return;
128 
129  for(int i = 0; i < kXorY; i++) cairo_set_line_width(cr[i], 1.0);
130 
131  std::vector<hit> & THEhits = theevents[gevi].hits;
132 
133  std::sort(THEhits.begin(), THEhits.end(), by_charge);
134 
135  const int big = 100000;
136  const bool bigevent = THEhits.size() > big;
137 
138  int ndrawn = 0;
139  for(unsigned int i = 0; i < THEhits.size(); i++){
140  const hit & thishit = THEhits[i];
141 
142  if(thishit.tdc < drawpars->firsttick ||
143  thishit.tdc > drawpars->lasttick) continue;
144 
145  if(bigevent && (++ndrawn)%big == 0)
146  set_eventn_status_progress(ndrawn, THEhits.size());
147 
148  draw_hit(cr[thishit.plane%2 == 1?kX:kY], thishit, edarea);
149  }
150 }
151 
GtkWidget * edarea[kXorY]
Definition: drawing.cxx:20
int pixy
Definition: geo.cxx:24
static bool by_charge(const hit &a, const hit &b)
Definition: hits.cxx:15
int pixx
Definition: geo.cxx:24
Supply basic geometry functions.
void set_eventn_status_progress(const int nhit, const int tothits)
Definition: status.cxx:182
Definition: geo.h:1
uint16_t plane
Definition: event.h:2
void red()
Definition: red.C:20
int active_plane
Definition: main.cxx:78
int32_t tdc
Definition: event.h:5
uint16_t cell
Definition: event.h:2
int gevi
Definition: main.cxx:76
const Var kY([](const caf::SRProxy *sr){float tmp=0.f;if(sr->mc.nu.empty()) return tmp;tmp=sr->mc.nu[0].y;return tmp;})
__attribute__((unused)) static bool by_time(const hit &a
void hits()
Definition: readHits.C:15
tuple blue
Definition: rootlogon.py:65
std::vector< noeevent > theevents
Definition: noe_module.cc:28
void draw_hits(cairo_t **cr, const DRAWPARS *const drawpars, GtkWidget **edarea)
Definition: hits.cxx:125
const double a
int16_t adc
Definition: event.h:3
int active_cell
Definition: main.cxx:78
int det_to_screen_y(const int plane, const int cell)
Definition: geo.cxx:119
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
void draw_hit(cairo_t *cr, const hit &thishit, GtkWidget **edarea)
Definition: hits.cxx:67
static void colorhit(const int32_t adc, float &red, float &green, float &blue, const bool active)
Definition: hits.cxx:28
Definition: event.h:1
Definition: geo.h:1
const hit & b
Definition: hits.cxx:21
int scintpix_from_pixx(const int x)
Definition: geo.cxx:61
int det_to_screen_x(const int plane)
Definition: geo.cxx:100
noe_view_t
Definition: geo.h:1
int32_t firsttick
Definition: drawing.h:4
int32_t lasttick
Definition: drawing.h:4