Changeset 5859862 in sasview
- Timestamp:
- Sep 20, 2009 3:41:40 PM (15 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- a65ffcb
- Parents:
- a1100c07
- Location:
- DataLoader
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
DataLoader/extensions/smearer.cpp
ra3f8d58 r5859862 33 33 // whether we need to compute one 34 34 has_matrix = false; 35 even_binning = true; 36 }; 37 38 /** 39 * Constructor for BaseSmearer 40 * 41 * Used for uneven binning 42 * @param q: array of Q values 43 * @param nbins: number of Q bins 44 */ 45 BaseSmearer :: BaseSmearer(double* q, int nbins) { 46 // Number of bins 47 this->nbins = nbins; 48 this->q_values = q; 49 // Flag to keep track of whether we have a smearing matrix or 50 // whether we need to compute one 51 has_matrix = false; 52 even_binning = false; 35 53 }; 36 54 … … 50 68 }; 51 69 52 /** 53 * Constructor for SlitSmearer 54 * 55 * @param width: array slit widths for each Q point, in Q units 56 * @param qmin: minimum Q value 57 * @param qmax: maximum Q value 58 * @param nbins: number of Q bins 59 */ 70 /** 71 * Constructor for SlitSmearer 72 * 73 * @param width: slit width in Q units 74 * @param height: slit height in Q units 75 * @param q: array of Q values 76 * @param nbins: number of Q bins 77 */ 78 SlitSmearer :: SlitSmearer(double width, double height, double* q, int nbins) : 79 BaseSmearer(q, nbins){ 80 this->height = height; 81 this->width = width; 82 }; 83 84 /** 85 * Constructor for QSmearer 86 * 87 * @param width: array slit widths for each Q point, in Q units 88 * @param qmin: minimum Q value 89 * @param qmax: maximum Q value 90 * @param nbins: number of Q bins 91 */ 60 92 QSmearer :: QSmearer(double* width, double qmin, double qmax, int nbins) : 61 93 BaseSmearer(qmin, qmax, nbins){ … … 64 96 65 97 /** 98 * Constructor for QSmearer 99 * 100 * @param width: array slit widths for each Q point, in Q units 101 * @param q: array of Q values 102 * @param nbins: number of Q bins 103 */ 104 QSmearer :: QSmearer(double* width, double* q, int nbins) : 105 BaseSmearer(q, nbins){ 106 this->width = width; 107 }; 108 109 /** 66 110 * Compute the slit smearing matrix 111 * 112 * For even binning (q_min to q_max with nbins): 113 * 114 * step = (q_max-q_min)/(nbins-1) 115 * first bin goes from q_min to q_min+step 116 * last bin goes from q_max to q_max+step 117 * 118 * For binning according to q array: 119 * 120 * Each q point represents a bin going from half the distance between it 121 * and the previous point to half the distance between it and the next point. 122 * 123 * Example: bin i goes from (q_values[i-1]+q_values[i])/2 to (q_values[i]+q_values[i+1])/2 124 * 125 * The exceptions are the first and last bins, which are centered at the first and 126 * last q-values, respectively. The width of the first and last bins is the distance between 127 * their respective neighboring q-value. 67 128 */ 68 129 void SlitSmearer :: compute_matrix(){ 69 130 70 131 weights = new vector<double>(nbins*nbins,0); 132 133 // Check the length of the data 134 if (nbins<2) return; 71 135 72 136 // Loop over all q-values 73 137 for(int i=0; i<nbins; i++) { 74 double q = qmin + (double)i*(qmax-qmin)/((double)nbins-1.0); 138 double q, q_min, q_max; 139 get_bin_range(i, &q, &q_min, &q_max); 75 140 76 141 // For each q-value, compute the weight of each other q-bin … … 102 167 } 103 168 double q_shifted = sqrt( ((q-shift_w)*(q-shift_w) + shift_h*shift_h) ); 104 int q_i = (int)(floor( (q_shifted-qmin) /((qmax-qmin)/((double)nbins -1.0)) )); 169 170 // Find in which bin this shifted value belongs 171 int q_i=nbins; 172 if (even_binning) { 173 // This is kept for backward compatibility since the binning 174 // was originally defined differently for even bins. 175 q_i = (int)(floor( (q_shifted-qmin) /((qmax-qmin)/((double)nbins -1.0)) )); 176 } else { 177 for(int t=0; t<nbins; t++) { 178 double q_t, q_high, q_low; 179 get_bin_range(t, &q_t, &q_low, &q_high); 180 if(q_shifted>=q_low && q_shifted<q_high) { 181 q_i = t; 182 break; 183 } 184 } 185 } 105 186 106 187 // Skip the entries outside our I(q) range … … 121 202 // Loop over all q-values 122 203 double step = (qmax-qmin)/((double)nbins-1.0); 204 double q, q_min, q_max; 205 double q_j, q_jmax, q_jmin; 123 206 for(int i=0; i<nbins; i++) { 124 double q = qmin + (double)i*step; 125 double q_min = q - 0.5*step; 126 double q_max = q + 0.5*step; 207 get_bin_range(i, &q, &q_min, &q_max); 127 208 128 209 for(int j=0; j<nbins; j++) { 129 double q_j = qmin + (double)j*step;210 get_bin_range(j, &q_j, &q_jmin, &q_jmax); 130 211 131 212 // Compute the fraction of the Gaussian contributing … … 139 220 140 221 /** 222 * Computes the Q range of a given bin of the Q distribution. 223 * The range is computed according the the data distribution that 224 * was given to the object at initialization. 225 * 226 * @param i: number of the bin in the distribution 227 * @param q: q-value of bin i 228 * @param q_min: lower bound of the bin 229 * @param q_max: higher bound of the bin 230 * 231 */ 232 void BaseSmearer :: get_bin_range(int i, double* q, double* q_min, double* q_max) { 233 if (even_binning) { 234 double step = (qmax-qmin)/((double)nbins-1.0); 235 *q = qmin + (double)i*step; 236 *q_min = *q - 0.5*step; 237 *q_max = *q + 0.5*step; 238 } else { 239 *q = q_values[i]; 240 if (i==0) { 241 double step = (q_values[1]-q_values[0])/2.0; 242 *q_min = *q - step; 243 *q_max = *q + step; 244 } else if (i==nbins-1) { 245 double step = (q_values[i]-q_values[i-1])/2.0; 246 *q_min = *q - step; 247 *q_max = *q + step; 248 } else { 249 *q_min = *q - (q_values[i]-q_values[i-1])/2.0; 250 *q_max = *q + (q_values[i+1]-q_values[i])/2.0; 251 } 252 } 253 } 254 255 /** 141 256 * Perform smearing by applying the smearing matrix to the input Q array 142 257 */ -
DataLoader/extensions/smearer.hh
ra3f8d58 r5859862 24 24 class BaseSmearer { 25 25 protected: 26 // Internal flag: true when the weights vector is filled 26 27 bool has_matrix; 27 // Smearing matrix 28 vector<double>* weights; 28 // True when only qmin, qmax and nbins are given. Bins are equidistant 29 bool even_binning; 30 // Smearing matrix 31 vector<double>* weights; 32 // Q vector 33 double* q_values; 29 34 // Q_min (Min Q-value for I(q)) 30 35 double qmin; … … 37 42 // Constructor 38 43 BaseSmearer(double qmin, double qmax, int nbins); 44 BaseSmearer(double* q, int nbins); 39 45 // Smear function 40 46 virtual void smear(double *, double *, int, int); … … 43 49 // Utility function to check the number of bins 44 50 int get_nbins() { return nbins; } 51 // Get the q range of a particular bin 52 virtual void get_bin_range(int, double*, double*, double*); 45 53 }; 46 54 … … 63 71 // Constructor 64 72 SlitSmearer(double width, double height, double qmin, double qmax, int nbins); 73 SlitSmearer(double width, double height, double* q, int nbins); 65 74 // Compute the smearing matrix 66 75 virtual void compute_matrix(); … … 80 89 81 90 // Constructor 82 QSmearer(double* width,double qmin, double qmax, int nbins); 91 QSmearer(double* width, double qmin, double qmax, int nbins); 92 QSmearer(double* width, double* q, int nbins); 83 93 // Compute the smearing matrix 84 94 virtual void compute_matrix(); -
DataLoader/extensions/smearer_module.cpp
ra3f8d58 r5859862 54 54 55 55 /** 56 * Create a SlitSmearer as a python object by supplying a q array 57 */ 58 PyObject * new_slit_smearer_with_q(PyObject *, PyObject *args) { 59 PyObject *qvalues_obj; 60 Py_ssize_t n_q; 61 double* qvalues; 62 double width; 63 double height; 64 65 if (!PyArg_ParseTuple(args, "ddO", &width, &height, &qvalues_obj)) return NULL; 66 OUTVECTOR(qvalues_obj, qvalues, n_q); 67 SlitSmearer* smearer = new SlitSmearer(width, height, qvalues, n_q); 68 return PyCObject_FromVoidPtr(smearer, del_slit_smearer); 69 } 70 71 /** 56 72 * Delete a QSmearer object 57 73 */ … … 76 92 OUTVECTOR(width_obj, width, n_w); 77 93 QSmearer* smearer = new QSmearer(width, qmin, qmax, nbins); 94 return PyCObject_FromVoidPtr(smearer, del_q_smearer); 95 } 96 97 /** 98 * Create a QSmearer as a python object by supplying a q array 99 */ 100 PyObject * new_q_smearer_with_q(PyObject *, PyObject *args) { 101 PyObject *width_obj; 102 Py_ssize_t n_w; 103 double* width; 104 PyObject *qvalues_obj; 105 Py_ssize_t n_q; 106 double* qvalues; 107 108 if (!PyArg_ParseTuple(args, "OO", &width_obj, &qvalues_obj)) return NULL; 109 OUTVECTOR(width_obj, width, n_w); 110 OUTVECTOR(qvalues_obj, qvalues, n_q); 111 QSmearer* smearer = new QSmearer(width, qvalues, n_q); 78 112 return PyCObject_FromVoidPtr(smearer, del_q_smearer); 79 113 } … … 114 148 } 115 149 150 /** 151 * Get the q-value of a given bin 152 */ 153 PyObject * get_q(PyObject *, PyObject *args) { 154 PyObject *smear_obj; 155 int bin; 156 157 if (!PyArg_ParseTuple(args, "Oi", &smear_obj, &bin)) return NULL; 158 159 // Set the array pointers 160 void *temp = PyCObject_AsVoidPtr(smear_obj); 161 BaseSmearer* s = static_cast<BaseSmearer *>(temp); 162 163 double q, q_min, q_max; 164 s->get_bin_range(bin, &q, &q_min, &q_max); 165 166 return Py_BuildValue("d", q); 167 } 168 116 169 117 170 /** … … 121 174 {"new_slit_smearer", (PyCFunction)new_slit_smearer, METH_VARARGS, 122 175 "Create a new Slit Smearer object"}, 176 {"new_slit_smearer_with_q", (PyCFunction)new_slit_smearer_with_q, METH_VARARGS, 177 "Create a new Slit Smearer object by supplying an array of Q values"}, 123 178 {"new_q_smearer", (PyCFunction)new_q_smearer, METH_VARARGS, 124 179 "Create a new Q Smearer object"}, 180 {"new_q_smearer_with_q", (PyCFunction)new_q_smearer_with_q, METH_VARARGS, 181 "Create a new Q Smearer object by supplying an array of Q values"}, 125 182 {"smear",(PyCFunction)smear_input, METH_VARARGS, 126 183 "Smear the given input array"}, 184 {"get_q",(PyCFunction)get_q, METH_VARARGS, 185 "Get the q-value of a given bin"}, 127 186 {NULL} 128 187 }; -
DataLoader/qsmearing.py
ra3f8d58 r5859862 12 12 import numpy 13 13 import math 14 import logging, sys 14 15 import scipy.special 15 16 … … 99 100 100 101 def _compute_matrix(self): return NotImplemented 102 103 def get_bin_range(self, q_min=None, q_max=None): 104 """ 105 @param q_min: minimum q-value to smear 106 @param q_max: maximum q-value to smear 107 """ 108 if q_min == None: 109 q_min = self.min 110 111 if q_max == None: 112 q_max = self.max 113 114 _qmin_unsmeared, _qmax_unsmeared = self.get_unsmeared_range(q_min, q_max) 115 116 _first_bin = None 117 _last_bin = None 118 119 step = (self.max-self.min)/(self.nbins-1.0) 120 for i in range(self.nbins): 121 q_i = smearer.get_q(self._smearer, i) 122 if (q_i >= _qmin_unsmeared) and (q_i <= _qmax_unsmeared): 123 # Identify first and last bin 124 if _first_bin is None: 125 _first_bin = i 126 else: 127 _last_bin = i 128 129 return _first_bin, _last_bin 101 130 102 131 def __call__(self, iq_in, first_bin=0, last_bin=None): … … 161 190 This method HAS to be called before smearing 162 191 """ 163 self._smearer = smearer.new_slit_smearer(self.width, self.height, self.min, self.max, self.nbins) 192 #self._smearer = smearer.new_slit_smearer(self.width, self.height, self.min, self.max, self.nbins) 193 self._smearer = smearer.new_slit_smearer_with_q(self.width, self.height, self.qvalues) 164 194 self._init_complete = True 165 195 196 def get_unsmeared_range(self, q_min, q_max): 197 """ 198 Determine the range needed in unsmeared-Q to cover 199 the smeared Q range 200 """ 201 # Range used for input to smearing 202 _qmin_unsmeared = q_min 203 _qmax_unsmeared = q_max 204 try: 205 _qmin_unsmeared = self.min 206 _qmax_unsmeared = self.max 207 except: 208 logging.error("_SlitSmearer.get_bin_range: %s" % sys.exc_value) 209 return _qmin_unsmeared, _qmax_unsmeared 166 210 167 211 class SlitSmearer(_SlitSmearer): … … 199 243 self.nbins = len(data1D.x) 200 244 ## Minimum Q 201 self.min = data1D.x[0]245 self.min = min(data1D.x) 202 246 ## Maximum 203 self.max = data1D.x[len(data1D.x)-1] 204 205 #print "nbin,npts",self.nbins,self.npts 247 self.max = max(data1D.x) 248 ## Q-values 249 self.qvalues = data1D.x 250 206 251 207 252 class _QSmearer(_BaseSmearer): … … 236 281 This method HAS to be called before smearing 237 282 """ 238 self._smearer = smearer.new_q_smearer(numpy.asarray(self.width), self.min, self.max, self.nbins) 283 #self._smearer = smearer.new_q_smearer(numpy.asarray(self.width), self.min, self.max, self.nbins) 284 self._smearer = smearer.new_q_smearer_with_q(numpy.asarray(self.width), self.qvalues) 239 285 self._init_complete = True 286 287 def get_unsmeared_range(self, q_min, q_max): 288 """ 289 Determine the range needed in unsmeared-Q to cover 290 the smeared Q range 291 Take 3 sigmas as the offset between smeared and unsmeared space 292 """ 293 # Range used for input to smearing 294 _qmin_unsmeared = q_min 295 _qmax_unsmeared = q_max 296 try: 297 offset = 3.0*max(self.width) 298 _qmin_unsmeared = max([self.min, q_min-offset]) 299 _qmax_unsmeared = min([self.max, q_max+offset]) 300 except: 301 logging.error("_QSmearer.get_bin_range: %s" % sys.exc_value) 302 return _qmin_unsmeared, _qmax_unsmeared 303 304 240 305 241 306 class QSmearer(_QSmearer): … … 260 325 self.nbins = len(data1D.x) 261 326 ## Minimum Q 262 self.min = data1D.x[0]327 self.min = min(data1D.x) 263 328 ## Maximum 264 self.max = data1D.x[len(data1D.x)-1] 329 self.max = max(data1D.x) 330 ## Q-values 331 self.qvalues = data1D.x 265 332 266 333 -
DataLoader/test/utest_smearing.py
ra3f8d58 r5859862 54 54 input = 12.0-numpy.arange(1,11) 55 55 output = s(input) 56 answer = [ 9.666, 9.056, 8.329, 7.494, 6.642, 5.721, 4.774, 3.824, 2.871, 2. ] 56 # The following commented line was the correct output for even bins [see smearer.cpp for details] 57 #answer = [ 9.666, 9.056, 8.329, 7.494, 6.642, 5.721, 4.774, 3.824, 2.871, 2. ] 58 answer = [ 9.2302, 8.6806, 7.9533, 7.1673, 6.2889, 5.4, 4.5028, 3.5744, 2.6083, 2. ] 57 59 for i in range(len(input)): 58 60 self.assertAlmostEqual(answer[i], output[i], 2)
Note: See TracChangeset
for help on using the changeset viewer.