UltraScan III
us_ri_noise.cpp
Go to the documentation of this file.
1 
3 #include "us_ri_noise.h"
4 #include "us_settings.h"
5 #include "us_gui_settings.h"
6 #include "us_matrix.h"
7 
9  const QList< int >& Includes,
10  double left,
11  double right,
12  const QString& dataType,
13  int& initial_order,
14  QList< double >& r )
15  : US_WidgetsDialog( 0, 0 ),
16  data( raw ), includes( Includes ), range_left( left ),
17  range_right( right ), order( initial_order ), residuals( r )
18 {
19  setWindowTitle( tr( "Determine Radial Invariant Noise" ) );
20  setPalette( US_GuiSettings::frameColor() );
21 
22  QHBoxLayout* main = new QHBoxLayout( this );
23  main->setSpacing ( 2 );
24  main->setContentsMargins( 2, 2, 2, 2 );
25 
26  if ( order < 4 ) order = 4;
27 
28  QVBoxLayout* info = new QVBoxLayout();
29 
31  us_setReadOnly( te_details, true );
32  info->addWidget( te_details );
33 
34  QHBoxLayout* spin = new QHBoxLayout;
35 
36  QLabel* lb_spin = us_label( tr( "Fit Order:" ) );
37  spin->addWidget( lb_spin );
38 
39  ct_order = us_counter( 1, 4.0, 9.0, (double)order );
40  ct_order->setStep( 1.0 );
41  connect( ct_order, SIGNAL( valueChanged ( double ) ),
42  SLOT ( draw_fit ( double ) ) );
43  spin->addWidget( ct_order );
44  info->addLayout( spin );
45 
46  // Button Row
47  QHBoxLayout* buttons = new QHBoxLayout;
48 
49  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
50  connect( pb_cancel, SIGNAL( clicked() ), SLOT( reject() ) );
51  buttons->addWidget( pb_cancel );
52 
53  QPushButton* pb_accept = us_pushbutton( tr( "Accept" ) );
54  connect( pb_accept, SIGNAL( clicked() ), SLOT( accept() ) );
55  buttons->addWidget( pb_accept );
56 
57  info->addLayout( buttons );
58 
59  main->addLayout( info );
60 
61  QString y_axis = tr( "Absorbance" );
62  if ( dataType == "IP" ) y_axis = tr( "Fringes" );
63 
64  QBoxLayout* plot = new US_Plot( data_plot,
65  tr( "RI Noise Fit" ),
66  tr( "Scan Time (seconds)" ), y_axis );
67 
68  data_plot->setMinimumSize( 600, 400 );
69  us_grid( data_plot );
70 
71  main->addLayout( plot );
72 
73  draw_fit( order );
74 }
75 
76 void US_RiNoise::draw_fit( double new_order )
77 {
78  order = (int)new_order;
79 
80  int scan_count = data.scanData.size();
81 
82  double* coeffs = new double[ order ];
83  double* absorbance_integral = new double[ scan_count ];
84  double* fit = new double[ scan_count ];
85  double* scan_time = new double[ scan_count ];;
86 
87  // Calculate the integral of each scan which is needed for the least-squares
88  // polynomial fit to correct for radially invariant baseline noise. We also
89  // keep track of the total integral at each point.
90 
91  int scan = 0;
92 
93  for ( int i = 0; i < scan_count; i++ )
94  {
95  if ( ! includes.contains( i ) ) continue;
96 
97  const US_DataIO::Scan* s = &data.scanData[ i ];
98 
99  int indexLeft = US_DataIO::index( data.xvalues, range_left );
100  int indexRight = US_DataIO::index( data.xvalues, range_right );
101 
102  double delta_r = ( range_right - range_left ) /
103  ( indexRight - indexLeft );
104 
105  absorbance_integral[ scan ] = 0.0;
106 
107  // Integrate using trapezoid rule
108  for ( int j = indexLeft + 1; j <= indexRight; j++ )
109  {
110  double avg = ( s->rvalues[ j ] + s->rvalues[ j - 1 ] ) / 2.0;
111 
112  absorbance_integral[ scan ] += avg * delta_r;
113  }
114 
115  scan++;
116  }
117 
118  scan = 0;
119 
120  for ( int i = 0; i < scan_count; i++ )
121  {
122  if ( ! includes.contains( i ) ) continue;
123  scan_time[ scan++ ] = data.scanData[ i ].seconds;
124  }
125 
126  US_Matrix::lsfit( coeffs, scan_time, absorbance_integral, scan, order );
127 
128  residuals.clear();
129  scan = 0;
130 
131  for ( int i = 0; i < scan_count; i++ )
132  {
133  if ( includes.contains( i ) )
134  {
135  fit[ scan ] = 0;
136 
137  for ( int j = 0; j < order; j++ )
138  fit[ scan ] += coeffs[ j ] * pow( data.scanData[ i ].seconds, j );
139 
140  residuals << absorbance_integral[ scan ] - fit[ scan ];
141  scan++;
142  }
143  else
144  residuals << 0.0; // Fill in holes for deleted scans
145  }
146 
147  // Write the coefficients
148  te_details->clear();
149  QString s = tr( "Coefficients for %1th order polynomial fit\n" ).arg( order );
150  te_details->append( s );
151 
152  for ( int i = 0; i < order; i++ )
153  {
154  QString coef = QString::number( coeffs[ i ], 'e', 6 );
155  if ( coef.at( 0 ) != '-' ) coef.prepend( " " );
156  s = tr( "Coefficient %1: " ).arg( i + 1 ) + coef;
157  te_details->append( s );
158  }
159 
160  data_plot->detachItems( QwtPlotItem::Rtti_PlotCurve );
161 
162  // Plot against the time of the scan:
163  scan = 0;
164 
165  for ( int i = 0; i < scan_count; i++ )
166  {
167  if ( ! includes.contains( i ) ) continue;
168  scan_time[ scan ] = data.scanData[ i ].seconds;
169  scan++;
170  }
171 
172  QwtPlotCurve* integrals = us_curve( data_plot, tr( "Integrals" ) );
173  integrals->setData( scan_time, absorbance_integral, scan );
174  integrals->setPen( QPen( Qt::yellow ) );
175 
176  QwtPlotCurve* polyfit = us_curve( data_plot, tr( "Polynomial Fit" ) );
177  polyfit->setData( scan_time, fit, scan );
178  integrals->setPen( QPen( Qt::magenta ) );
179 
180  data_plot->replot();
181 
182  delete [] coeffs;
183  delete [] absorbance_integral;
184  delete [] fit;
185  delete [] scan_time;
186 }
187 
188 
189 // We want to be able to call this function from other places.
191  const QList< int >& includes,
192  double range_left,
193  double range_right,
194  int order,
195  QList< double >& residuals )
196 {
197  int scan_count = data.scanData.size();
198 
199  double* coeffs = new double[ order ];
200  double* absorbance_integral = new double[ scan_count ];
201  double* fit = new double[ scan_count ];
202  double* scan_time = new double[ scan_count ];;
203 
204  // Calculate the integral of each scan which is needed for the least-squares
205  // polynomial fit to correct for radially invariant baseline noise. We also
206  // keep track of the total integral at each point.
207 
208  int scan = 0;
209 
210  for ( int i = 0; i < scan_count; i++ )
211  {
212  if ( ! includes.contains( i ) ) continue;
213 
214  const US_DataIO::Scan* s = &data.scanData[ i ];
215 
216  int indexLeft = US_DataIO::index( data.xvalues, range_left );
217  int indexRight = US_DataIO::index( data.xvalues, range_right );
218 
219  double delta_r = ( range_right - range_left ) /
220  ( indexRight - indexLeft );
221 
222  absorbance_integral[ scan ] = 0.0;
223 
224  // Integrate using trapezoid rule
225  for ( int j = indexLeft + 1; j <= indexRight; j++ )
226  {
227  double avg = ( s->rvalues[ j ] + s->rvalues[ j - 1 ] ) / 2.0;
228 
229  absorbance_integral[ scan ] += avg * delta_r;
230  }
231 
232  scan++;
233  }
234 
235  scan = 0;
236 
237  for ( int i = 0; i < scan_count; i++ )
238  {
239  if ( ! includes.contains( i ) ) continue;
240  scan_time[ scan++ ] = data.scanData[ i ].seconds;
241  }
242 
243  US_Matrix::lsfit( coeffs, scan_time, absorbance_integral, scan, order );
244 
245  residuals.clear();
246  scan = 0;
247 
248  for ( int i = 0; i < scan_count; i++ )
249  {
250  if ( includes.contains( i ) )
251  {
252  fit[ scan ] = 0;
253 
254  for ( int j = 0; j < order; j++ )
255  fit[ scan ] += coeffs[ j ] * pow( data.scanData[ i ].seconds, j );
256 
257  residuals << absorbance_integral[ scan ] - fit[ scan ];
258  scan++;
259  }
260  else
261  residuals << 0.0; // Fill in holes for deleted scans
262 
263  }
264 
265  delete [] coeffs;
266  delete [] absorbance_integral;
267  delete [] fit;
268  delete [] scan_time;
269 }