Changeset 095ab1b in sasview
- Timestamp:
- Mar 12, 2010 12:39:01 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:
- a4d4b35
- Parents:
- 3cd95c8
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
DataLoader/manipulations.py
r3c67340 r095ab1b 50 50 out=get_q(dx, dy, det_dist, wavelength) 51 51 return out 52 52 53 def flip_phi(phi): 54 """ 55 Correct phi to within the 0 <= to <= 2pi range 56 @return: phi in >=0 and <=2Pi 57 """ 58 Pi = math.pi 59 if phi < 0: 60 phi_out = phi + 2*Pi 61 elif phi > 2*Pi: 62 phi_out = phi - 2*Pi 63 else: 64 phi_out = phi 65 return phi_out 66 67 def reader2D_converter(data2d=None): 68 """ 69 convert old 2d format opened by IhorReader or danse_reader to new Data2D format 70 @param data2d: 2d array of Data2D object 71 @return: 1d arrays of Data2D object 72 """ 73 if data2d.data==None or data2d.x_bins==None or data2d.y_bins==None: 74 raise ValueError,"Can't convert this data: data=None..." 75 76 from DataLoader.data_info import Data2D 77 78 new_x = numpy.tile(data2d.x_bins, (len(data2d.y_bins),1)) 79 new_y = numpy.tile(data2d.y_bins, (len(data2d.x_bins),1)) 80 new_y = new_y.swapaxes(0,1) 81 82 new_data = data2d.data.flatten() 83 new_err_data = data2d.err_data.flatten() 84 qx_data = new_x.flatten() 85 qy_data = new_y.flatten() 86 q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data) 87 mask = numpy.ones(len(new_data), dtype = bool) 88 89 output = Data2D() 90 output = data2d 91 output.data = new_data 92 output.err_data = new_err_data 93 output.qx_data = qx_data 94 output.qy_data = qy_data 95 output.q_data = q_data 96 output.mask = mask 97 98 return output 99 53 100 class _Slab(object): 54 101 """ … … 84 131 raise RuntimeError, "_Slab._avg: invalid number of detectors: %g" % len(data2D.detector) 85 132 86 pixel_width_x = data2D.detector[0].pixel_size.x87 pixel_width_y = data2D.detector[0].pixel_size.y88 det_dist = data2D.detector[0].distance89 wavelength = data2D.source.wavelength90 center_x = data2D.detector[0].beam_center.x/pixel_width_x91 center_y = data2D.detector[0].beam_center.y/pixel_width_y92 133 # Get data 134 data = data2D.data 135 q_data = data2D.q_data 136 err_data = data2D.err_data 137 qx_data = data2D.qx_data 138 qy_data = data2D.qy_data 139 93 140 # Build array of Q intervals 94 141 if maj=='x': 95 nbins = int(math.ceil((self.x_max-self.x_min)/self.bin_width)) 96 qbins = self.bin_width*numpy.arange(nbins)+self.x_min 142 if self.fold: x_min = 0 143 else: x_min = self.x_min 144 nbins = int(math.ceil((self.x_max-x_min)/self.bin_width)) 145 qbins = self.bin_width*numpy.arange(nbins)+ x_min 97 146 elif maj=='y': 98 nbins = int(math.ceil((self.y_max-self.y_min)/self.bin_width)) 99 qbins = self.bin_width*numpy.arange(nbins)+self.y_min 147 if self.fold: y_min = 0 148 else: y_min = self.y_min 149 nbins = int(math.ceil((self.y_max-y_min)/self.bin_width)) 150 qbins = self.bin_width*numpy.arange(nbins)+ y_min 100 151 else: 101 152 raise RuntimeError, "_Slab._avg: unrecognized axis %s" % str(maj) … … 105 156 err_y = numpy.zeros(nbins) 106 157 y_counts = numpy.zeros(nbins) 107 108 for i in range(numpy.size(data2D.data,1)): 109 # Min and max x-value for the pixel 110 minx = pixel_width_x*(i - center_x) 111 maxx = pixel_width_x*(i+1.0 - center_x) 112 113 qxmin = get_q(minx, 0.0, det_dist, wavelength) 114 qxmax = get_q(maxx, 0.0, det_dist, wavelength) 115 116 # Get the count fraction in x for that pixel 117 frac_min = get_pixel_fraction_square(self.x_min, qxmin, qxmax) 118 frac_max = get_pixel_fraction_square(self.x_max, qxmin, qxmax) 119 frac_x = frac_max - frac_min 120 121 if frac_x == 0: 122 continue 123 124 if maj=='x': 125 dx = pixel_width_x*(i+0.5 - center_x) 126 q_value = get_q(dx, 0.0, det_dist, wavelength) 127 if self.fold==False and dx<0: 128 q_value = -q_value 129 i_q = int(math.ceil((q_value-self.x_min)/self.bin_width)) - 1 130 131 if i_q<0 or i_q>=nbins: 132 continue 133 134 for j in range(numpy.size(data2D.data,0)): 135 # Min and max y-value for the pixel 136 miny = pixel_width_y*(j - center_y) 137 maxy = pixel_width_y*(j+1.0 - center_y) 138 139 qymin = get_q(0.0, miny, det_dist, wavelength) 140 qymax = get_q(0.0, maxy, det_dist, wavelength) 141 142 # Get the count fraction in x for that pixel 143 frac_min = get_pixel_fraction_square(self.y_min, qymin, qymax) 144 frac_max = get_pixel_fraction_square(self.y_max, qymin, qymax) 145 frac_y = frac_max - frac_min 146 147 frac = frac_x * frac_y 148 149 if frac == 0: 150 continue 151 152 if maj=='y': 153 dy = pixel_width_y*(j+0.5 - center_y) 154 q_value = get_q(0.0, dy, det_dist, wavelength) 155 if self.fold==False and dy<0: 156 q_value = -q_value 157 i_q = int(math.ceil((q_value-self.y_min)/self.bin_width)) - 1 158 159 if i_q<0 or i_q>=nbins: 160 continue 161 162 x[i_q] = q_value 163 y[i_q] += frac * data2D.data[j][i] 164 if data2D.err_data == None or data2D.err_data[j][i]==0.0: 165 err_y[i_q] += frac * frac * math.fabs(data2D.data[j][i]) 166 else: 167 err_y[i_q] += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i] 168 y_counts[i_q] += frac 169 170 # Average the sums 171 for i in range(nbins): 172 if y_counts[i]>0: 173 err_y[i] = math.sqrt(err_y[i])/y_counts[i] 174 y[i] = y[i]/y_counts[i] 175 176 return Data1D(x=x, y=y, dy=err_y) 158 159 # Average pixelsize in q space 160 for npts in range(len(data)): 161 # default frac 162 frac_x = 0 163 frac_y = 0 164 # get ROI 165 if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]: 166 frac_x = 1 167 if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]: 168 frac_y = 1 169 170 frac = frac_x * frac_y 171 172 if frac == 0: continue 173 174 # binning: find axis of q 175 if maj=='x': 176 q_value = qx_data[npts] 177 min = x_min 178 if maj=='y': 179 q_value = qy_data[npts] 180 min = y_min 181 if self.fold and q_value<0: q_value = -q_value 182 183 # bin 184 i_q = int(math.ceil((q_value-min)/self.bin_width)) - 1 185 186 # skip outside of max bins 187 if i_q<0 or i_q>=nbins: continue 188 189 # give it full weight 190 #frac = 1 191 192 #TODO: find better definition of x[i_q] based on q_data 193 x[i_q] = min +(i_q+1)*self.bin_width/2.0 194 y[i_q] += frac * data[npts] 195 196 if err_data == None or err_data[npts]==0.0: 197 err_y[i_q] += frac * frac * math.fabs(data[npts]) 198 else: 199 err_y[i_q] += frac * frac * err_data[npts] * err_data[npts] 200 y_counts[i_q] += frac 201 202 # Average the sums 203 for n in range(nbins): 204 err_y[n] = math.sqrt(err_y[n]) 205 206 err_y = err_y/y_counts 207 y = y/y_counts 208 209 idx = (numpy.isfinite(y)& numpy.isfinite(x)) 210 211 if not idx.any(): 212 raise ValueError, "Average Error: No points inside ROI to average..." 213 elif len(y[idx])!= nbins: 214 print "resulted",nbins- len(y[idx]),"empty bin(s) due to tight binning..." 215 return Data1D(x=x[idx], y=y[idx], dy=err_y[idx]) 177 216 178 217 class SlabY(_Slab): … … 240 279 raise RuntimeError, "Circular averaging: invalid number of detectors: %g" % len(data2D.detector) 241 280 242 pixel_width_x = data2D.detector[0].pixel_size.x243 pixel_width_y = data2D.detector[0].pixel_size.y244 det_dist = data2D.detector[0].distance245 wavelength = data2D.source.wavelength246 center_x = data2D.detector[0].beam_center.x/pixel_width_x247 center_y = data2D.detector[0].beam_center.y/pixel_width_y248 281 # Get data 282 data = data2D.data 283 q_data = data2D.q_data 284 err_data = data2D.err_data 285 qx_data = data2D.qx_data 286 qy_data = data2D.qy_data 287 249 288 y = 0.0 250 289 err_y = 0.0 251 290 y_counts = 0.0 252 sign=1 253 for i in range(numpy.size(data2D.data,1)): 254 # Min and max x-value for the pixel 255 minx = pixel_width_x*(i - center_x) 256 maxx = pixel_width_x*(i+1.0 - center_x) 257 if minx>=0: 258 sign=1 291 292 # Average pixelsize in q space 293 for npts in range(len(data)): 294 # default frac 295 frac_x = 0 296 frac_y = 0 297 298 # get min and max at each points 299 qx = qx_data[npts] 300 qy = qy_data[npts] 301 302 # get the ROI 303 if self.x_min <= qx and self.x_max > qx: 304 frac_x = 1 305 if self.y_min <= qy and self.y_max > qy: 306 frac_y = 1 307 308 #Find the fraction along each directions 309 frac = frac_x * frac_y 310 if frac == 0: continue 311 312 y += frac * data[npts] 313 if err_data == None or err_data[npts]==0.0: 314 err_y += frac * frac * math.fabs(data[npts]) 259 315 else: 260 sign=-1 261 qxmin = sign*get_q(minx, 0.0, det_dist, wavelength) 262 if maxx>=0: 263 sign=1 264 else: 265 sign=-1 266 qxmax = sign*get_q(maxx, 0.0, det_dist, wavelength) 267 268 # Get the count fraction in x for that pixel 269 frac_min = get_pixel_fraction_square(self.x_min, qxmin, qxmax) 270 frac_max = get_pixel_fraction_square(self.x_max, qxmin, qxmax) 271 frac_x = frac_max - frac_min 272 273 for j in range(numpy.size(data2D.data,0)): 274 # Min and max y-value for the pixel 275 miny = pixel_width_y*(j - center_y) 276 maxy = pixel_width_y*(j+1.0 - center_y) 277 if miny>=0: 278 sign=1 279 else: 280 sign=-1 281 282 qymin = sign*get_q(0.0, miny, det_dist, wavelength) 283 if maxy>=0: 284 sign=1 285 else: 286 sign=-1 287 288 qymax = sign*get_q(0.0, maxy, det_dist, wavelength) 289 290 # Get the count fraction in x for that pixel 291 frac_min = get_pixel_fraction_square(self.y_min, qymin, qymax) 292 frac_max = get_pixel_fraction_square(self.y_max, qymin, qymax) 293 frac_y = frac_max - frac_min 294 295 frac = frac_x * frac_y 296 297 y += frac * data2D.data[j][i] 298 if data2D.err_data == None or data2D.err_data[j][i]==0.0: 299 err_y += frac * frac * math.fabs(data2D.data[j][i]) 300 else: 301 err_y += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i] 302 y_counts += frac 303 316 err_y += frac * frac * err_data[npts] * err_data[npts] 317 y_counts += frac 318 304 319 return y, err_y, y_counts 320 321 305 322 306 323 class Boxavg(Boxsum): … … 356 373 as a function of Q 357 374 """ 358 def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.00 1):375 def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005): 359 376 # Minimum radius included in the average [A-1] 360 377 self.r_min = r_min … … 371 388 @return: Data1D object 372 389 """ 373 if len(data2D.detector) != 1: 374 raise RuntimeError, "Circular averaging: invalid number of detectors: %g" % len(data2D.detector) 375 376 pixel_width_x = data2D.detector[0].pixel_size.x 377 pixel_width_y = data2D.detector[0].pixel_size.y 378 det_dist = data2D.detector[0].distance 379 wavelength = data2D.source.wavelength 380 center_x = data2D.detector[0].beam_center.x/pixel_width_x+0.5 381 center_y = data2D.detector[0].beam_center.y/pixel_width_y+0.5 382 383 # Find out the maximum Q range 384 xwidth = (numpy.size(data2D.data,1))*pixel_width_x 385 dx_max = xwidth - data2D.detector[0].beam_center.x 386 if xwidth-dx_max>dx_max: 387 dx_max = xwidth-dx_max 388 389 ywidth = (numpy.size(data2D.data,0))*pixel_width_y 390 dy_max = ywidth - data2D.detector[0].beam_center.y 391 if ywidth-dy_max>dy_max: 392 dy_max = ywidth-dy_max 393 394 qmax = get_q(dx_max, dy_max, det_dist, wavelength) 395 390 # Get data 391 data = data2D.data 392 err_data = data2D.err_data 393 q_data = data2D.q_data 394 395 q_data_max = numpy.max(q_data) 396 397 if len(data2D.q_data) == None: 398 raise RuntimeError, "Circular averaging: invalid q_data: %g" % data2D.q_data 399 396 400 # Build array of Q intervals 397 nbins = int(math.ceil(( qmax-self.r_min)/self.bin_width))401 nbins = int(math.ceil((self.r_max-self.r_min)/self.bin_width)) 398 402 qbins = self.bin_width*numpy.arange(nbins)+self.r_min 399 403 400 404 x = numpy.zeros(nbins) 401 405 y = numpy.zeros(nbins) 402 406 err_y = numpy.zeros(nbins) 403 407 y_counts = numpy.zeros(nbins) 404 405 for i in range(numpy.size(data2D.data,1)): 406 dx = pixel_width_x*(i+0.5 - center_x) 407 408 # Min and max x-value for the pixel 409 minx = pixel_width_x*(i - center_x) 410 maxx = pixel_width_x*(i+1.0 - center_x) 411 412 for j in range(numpy.size(data2D.data,0)): 413 dy = pixel_width_y*(j+0.5 - center_y) 414 415 q_value = get_q(dx, dy, det_dist, wavelength) 416 417 # Min and max y-value for the pixel 418 miny = pixel_width_y*(j - center_y) 419 maxy = pixel_width_y*(j+1.0 - center_y) 420 421 # Calculate the q-value for each corner 422 # q_[x min or max][y min or max] 423 q_00 = get_q(minx, miny, det_dist, wavelength) 424 q_01 = get_q(minx, maxy, det_dist, wavelength) 425 q_10 = get_q(maxx, miny, det_dist, wavelength) 426 q_11 = get_q(maxx, maxy, det_dist, wavelength) 427 428 # Look for intercept between each side of the pixel 429 # and the constant-q ring for qmax 430 frac_max = get_pixel_fraction(self.r_max, q_00, q_01, q_10, q_11) 431 432 # Look for intercept between each side of the pixel 433 # and the constant-q ring for qmin 434 frac_min = get_pixel_fraction(self.r_min, q_00, q_01, q_10, q_11) 435 436 # We are interested in the region between qmin and qmax 437 # therefore the fraction of the surface of the pixel 438 # that we will use to calculate the number of counts to 439 # include is given by: 440 frac = frac_max - frac_min 441 442 i_q = int(math.ceil((q_value-self.r_min)/self.bin_width)) - 1 443 if q_value > qmax or q_value < self.r_min: 444 continue 445 446 x[i_q] = q_value 447 y[i_q] += frac * data2D.data[j][i] 448 if data2D.err_data == None or data2D.err_data[j][i]==0.0: 449 err_y[i_q] += frac * frac * math.fabs(data2D.data[j][i]) 450 else: 451 err_y[i_q] += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i] 452 y_counts[i_q] += frac 453 454 # Average the sums 455 nzero = 0 456 for i in range(nbins): 457 if y_counts[i]>0: 458 err_y[i] = math.sqrt(err_y[i])/y_counts[i] 459 y[i] = y[i]/y_counts[i] 408 409 for npt in range(len(data)): 410 frac = 0 411 412 # q-value at the pixel (j,i) 413 q_value = q_data[npt] 414 415 data_n = data[npt] 416 417 ## No need to calculate the frac when all data are within range 418 if self.r_min >= self.r_max: 419 raise ValueError, "Limit Error: min > max ???" 420 421 if self.r_min <= q_value and q_value <= self.r_max: frac = 1 422 423 if frac == 0: continue 424 425 i_q = int(math.floor((q_value-self.r_min)/self.bin_width)) 426 427 # Take care of the edge case at phi = 2pi. 428 if i_q == nbins: 429 i_q = nbins -1 430 431 y[i_q] += frac * data_n 432 433 if err_data == None or err_data[npt]==0.0: 434 err_y[i_q] += frac * frac * math.fabs(data_n) 460 435 else: 461 nzero += 1 462 ## Get rid of NULL points 463 tx = numpy.zeros(nbins-nzero) 464 ty = numpy.zeros(nbins-nzero) 465 terr_y = numpy.zeros(nbins-nzero) 466 j=0 467 for i in range(nbins): 468 if err_y[i] != 0 : 469 tx[j] = x[i] 470 ty[j] = y[i] 471 terr_y[j] = err_y[i] 472 j+=1 473 474 return Data1D(x=tx, y=ty, dy=terr_y) 436 err_y[i_q] += frac * frac * err_data[npt] * err_data[npt] 437 y_counts[i_q] += frac 438 439 ## x should be the center value of each bins 440 x = qbins+self.bin_width/2 441 442 # Average the sums 443 for n in range(nbins): 444 err_y[n] = math.sqrt(err_y[n]) 445 446 err_y = err_y/y_counts 447 y = y/y_counts 448 idx = (numpy.isfinite(y))&(numpy.isfinite(x)) 449 450 if not idx.any(): 451 raise ValueError, "Average Error: No points inside ROI to average..." 452 elif len(y[idx])!= nbins: 453 print "resulted",nbins- len(y[idx]),"empty bin(s) due to tight binning..." 454 455 return Data1D(x=x[idx], y=y[idx], dy=err_y[idx]) 475 456 476 457 … … 484 465 around the ring as a function of phi. 485 466 486 """ 487 467 Phi_min and phi_max should be defined between 0 and 2*pi 468 in anti-clockwise starting from the x- axis on the left-hand side 469 """ 470 #Todo: remove center. 488 471 def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0,nbins=20 ): 489 472 # Minimum radius … … 509 492 raise RuntimeError, "Ring averaging only take plottable_2D objects" 510 493 511 data = data2D.data 512 qmin = self.r_min 513 qmax = self.r_max 514 515 if len(data2D.detector) != 1: 516 raise RuntimeError, "Ring averaging: invalid number of detectors: %g" % len(data2D.detector) 517 pixel_width_x = data2D.detector[0].pixel_size.x 518 pixel_width_y = data2D.detector[0].pixel_size.y 519 det_dist = data2D.detector[0].distance 520 wavelength = data2D.source.wavelength 521 #center_x = self.center_x/pixel_width_x 522 #center_y = self.center_y/pixel_width_y 523 center_x = data2D.detector[0].beam_center.x/pixel_width_x 524 center_y = data2D.detector[0].beam_center.y/pixel_width_y 525 526 494 Pi = math.pi 495 496 # Get data 497 data = data2D.data 498 err_data = data2D.err_data 499 q_data = data2D.q_data 500 qx_data = data2D.qx_data 501 qy_data = data2D.qy_data 502 503 q_data_max = numpy.max(q_data) 504 505 # Set space for 1d outputs 527 506 phi_bins = numpy.zeros(self.nbins_phi) 528 507 phi_counts = numpy.zeros(self.nbins_phi) … … 530 509 phi_err = numpy.zeros(self.nbins_phi) 531 510 532 for i in range(numpy.size(data,1)): 533 dx = pixel_width_x*(i+0.5 - center_x) 534 535 # Min and max x-value for the pixel 536 minx = pixel_width_x*(i - center_x) 537 maxx = pixel_width_x*(i+1.0 - center_x) 538 539 for j in range(numpy.size(data,0)): 540 dy = pixel_width_y*(j+0.5 - center_y) 541 542 q_value = get_q(dx, dy, det_dist, wavelength) 543 544 # Min and max y-value for the pixel 545 miny = pixel_width_y*(j - center_y) 546 maxy = pixel_width_y*(j+1.0 - center_y) 547 548 # Calculate the q-value for each corner 549 # q_[x min or max][y min or max] 550 q_00 = get_q(minx, miny, det_dist, wavelength) 551 q_01 = get_q(minx, maxy, det_dist, wavelength) 552 q_10 = get_q(maxx, miny, det_dist, wavelength) 553 q_11 = get_q(maxx, maxy, det_dist, wavelength) 554 555 # Look for intercept between each side of the pixel 556 # and the constant-q ring for qmax 557 frac_max = get_pixel_fraction(qmax, q_00, q_01, q_10, q_11) 558 559 # Look for intercept between each side of the pixel 560 # and the constant-q ring for qmin 561 frac_min = get_pixel_fraction(qmin, q_00, q_01, q_10, q_11) 562 563 # We are interested in the region between qmin and qmax 564 # therefore the fraction of the surface of the pixel 565 # that we will use to calculate the number of counts to 566 # include is given by: 567 568 frac = frac_max - frac_min 569 570 i_phi = int(math.ceil(self.nbins_phi*(math.atan2(dy, dx)+math.pi)/(2.0*math.pi))) - 1 571 572 phi_bins[i_phi] += frac * data[j][i] 573 574 if data2D.err_data == None or data2D.err_data[j][i]==0.0: 575 phi_err[i_phi] += frac * frac * math.fabs(data2D.data[j][i]) 576 else: 577 phi_err[i_phi] += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i] 578 phi_counts[i_phi] += frac 579 511 for npt in range(len(data)): 512 frac = 0 513 514 # q-value at the point (npt) 515 q_value = q_data[npt] 516 517 data_n = data[npt] 518 519 # phi-value at the point (npt) 520 phi_value=math.atan2(qy_data[npt],qx_data[npt])+Pi 521 522 if self.r_min <= q_value and q_value <= self.r_max: frac = 1 523 524 if frac == 0: continue 525 526 # binning 527 i_phi = int(math.floor((self.nbins_phi)*phi_value/(2*Pi))) 528 529 # Take care of the edge case at phi = 2pi. 530 if i_phi == self.nbins_phi: 531 i_phi = self.nbins_phi -1 532 533 phi_bins[i_phi] += frac * data[npt] 534 535 if err_data == None or err_data[npt] ==0.0: 536 phi_err[i_phi] += frac * frac * math.fabs(data_n) 537 else: 538 phi_err[i_phi] += frac * frac *err_data[npt]*err_data[npt] 539 phi_counts[i_phi] += frac 540 580 541 for i in range(self.nbins_phi): 581 542 phi_bins[i] = phi_bins[i] / phi_counts[i] 582 543 phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i] 583 phi_values[i] = 2.0*math.pi/self.nbins_phi*(1.0*i + 0.5)-math.pi # move the pi back to -pi <-->+pi 584 585 return Data1D(x=phi_values, y=phi_bins, dy=phi_err) 544 phi_values[i] = 2.0*math.pi/self.nbins_phi*(1.0*i + 0.5) 545 546 idx = (numpy.isfinite(phi_bins)) 547 548 if not idx.any(): 549 raise ValueError, "Average Error: No points inside ROI to average..." 550 elif len(phi_bins[idx])!= self.nbins_phi: 551 print "resulted",self.nbins_phi- len(phi_bins[idx]),"empty bin(s) due to tight binning..." 552 return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx]) 586 553 587 554 def get_pixel_fraction(qmax, q_00, q_01, q_10, q_11): … … 651 618 elif (q_00+q_01+q_10+q_11)/4.0 < qmax: 652 619 frac_max = 1.0 653 620 654 621 return frac_max 655 622 … … 683 650 return (q-q_1)/(q_0 - q_1) 684 651 return None 685 686 #This class can be removed. 687 class _Sectorold: 688 """ 689 Defines a sector region on a 2D data set. 690 The sector is defined by r_min, r_max, phi_min, phi_max, 691 and the position of the center of the ring. 692 Phi is defined between 0 and 2pi 693 """ 694 def __init__(self, r_min, r_max, phi_min, phi_max,nbins=20): 695 self.r_min = r_min 696 self.r_max = r_max 697 self.phi_min = phi_min 698 self.phi_max = phi_max 699 self.nbins = nbins 700 701 def _agv(self, data2D, run='phi'): 702 """ 703 Perform sector averaging. 704 705 @param data2D: Data2D object 706 @param run: define the varying parameter ('phi' or 'q') 707 @return: Data1D object 708 """ 709 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 710 raise RuntimeError, "Ring averaging only take plottable_2D objects" 711 712 data = data2D.data 713 qmax = self.r_max 714 qmin = self.r_min 715 716 if len(data2D.detector) != 1: 717 raise RuntimeError, "Ring averaging: invalid number of detectors: %g" % len(data2D.detector) 718 pixel_width_x = data2D.detector[0].pixel_size.x 719 pixel_width_y = data2D.detector[0].pixel_size.y 720 det_dist = data2D.detector[0].distance 721 wavelength = data2D.source.wavelength 722 center_x = data2D.detector[0].beam_center.x/pixel_width_x 723 center_y = data2D.detector[0].beam_center.y/pixel_width_y 724 725 y = numpy.zeros(self.nbins) 726 y_counts = numpy.zeros(self.nbins) 727 x = numpy.zeros(self.nbins) 728 y_err = numpy.zeros(self.nbins) 729 730 for i in range(numpy.size(data,1)): 731 dx = pixel_width_x*(i+0.5 - center_x) 732 733 # Min and max x-value for the pixel 734 minx = pixel_width_x*(i - center_x) 735 maxx = pixel_width_x*(i+1.0 - center_x) 736 737 for j in range(numpy.size(data,0)): 738 dy = pixel_width_y*(j+0.5 - center_y) 739 740 q_value = get_q(dx, dy, det_dist, wavelength) 741 742 # Min and max y-value for the pixel 743 miny = pixel_width_y*(j - center_y) 744 maxy = pixel_width_y*(j+1.0 - center_y) 745 746 # Calculate the q-value for each corner 747 # q_[x min or max][y min or max] 748 q_00 = get_q(minx, miny, det_dist, wavelength) 749 q_01 = get_q(minx, maxy, det_dist, wavelength) 750 q_10 = get_q(maxx, miny, det_dist, wavelength) 751 q_11 = get_q(maxx, maxy, det_dist, wavelength) 752 753 # Look for intercept between each side of the pixel 754 # and the constant-q ring for qmax 755 frac_max = get_pixel_fraction(qmax, q_00, q_01, q_10, q_11) 756 757 # Look for intercept between each side of the pixel 758 # and the constant-q ring for qmin 759 frac_min = get_pixel_fraction(qmin, q_00, q_01, q_10, q_11) 760 761 # We are interested in the region between qmin and qmax 762 # therefore the fraction of the surface of the pixel 763 # that we will use to calculate the number of counts to 764 # include is given by: 765 766 frac = frac_max - frac_min 767 768 # Compute phi and check whether it's within the limits 769 phi_value=math.atan2(dy,dx)+math.pi 770 # if phi_value<self.phi_min or phi_value>self.phi_max: 771 if phi_value<self.phi_min or phi_value>self.phi_max: 772 continue 773 774 # Check which type of averaging we need 775 if run.lower()=='phi': 776 i_bin = int(math.ceil(self.nbins*(phi_value-self.phi_min)/(self.phi_max-self.phi_min))) - 1 777 else: 778 # If we don't need this pixel, skip the rest of the work 779 #TODO: an improvement here would be to compute the average 780 # Q for the pixel from the part that is covered by 781 # the ring defined by q_min/q_max rather than the complete 782 # pixel 783 if q_value<self.r_min or q_value>self.r_max: 784 continue 785 i_bin = int(math.ceil(self.nbins*(q_value-self.r_min)/(self.r_max-self.r_min))) - 1 786 787 try: 788 y[i_bin] += frac * data[j][i] 789 except: 790 import sys 791 print sys.exc_value 792 print i_bin, frac 793 794 if data2D.err_data == None or data2D.err_data[j][i]==0.0: 795 y_err[i_bin] += frac * frac * math.fabs(data2D.data[j][i]) 796 else: 797 y_err[i_bin] += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i] 798 y_counts[i_bin] += frac 799 800 for i in range(self.nbins): 801 y[i] = y[i] / y_counts[i] 802 y_err[i] = math.sqrt(y_err[i]) / y_counts[i] 803 # Check which type of averaging we need 804 if run.lower()=='phi': 805 x[i] = (self.phi_max-self.phi_min)/self.nbins*(1.0*i + 0.5)+self.phi_min 806 else: 807 x[i] = (self.r_max-self.r_min)/self.nbins*(1.0*i + 0.5)+self.r_min 808 809 return Data1D(x=x, y=y, dy=y_err) 810 652 811 653 class _Sector: 812 654 """ … … 817 659 and phi_max could be less than phi_min. 818 660 819 Phi is defined between 0 and 2 pi820 """ 821 def __init__(self, r_min, r_max, phi_min , phi_max,nbins=20):661 Phi is defined between 0 and 2*pi in anti-clockwise starting from the x- axis on the left-hand side 662 """ 663 def __init__(self, r_min, r_max, phi_min=0, phi_max=2*math.pi,nbins=20): 822 664 self.r_min = r_min 823 665 self.r_max = r_max … … 826 668 self.nbins = nbins 827 669 670 828 671 def _agv(self, data2D, run='phi'): 829 672 """ … … 831 674 832 675 @param data2D: Data2D object 833 @param run: define the varying parameter ('phi' or 'q')676 @param run: define the varying parameter ('phi' , 'q' , or 'q2') 834 677 @return: Data1D object 835 678 """ 836 679 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 837 680 raise RuntimeError, "Ring averaging only take plottable_2D objects" 838 839 data = data2D.data 840 qmax = self.r_max 841 qmin = self.r_min 842 843 if len(data2D.detector) != 1: 844 raise RuntimeError, "Ring averaging: invalid number of detectors: %g" % len(data2D.detector) 845 pixel_width_x = data2D.detector[0].pixel_size.x 846 pixel_width_y = data2D.detector[0].pixel_size.y 847 det_dist = data2D.detector[0].distance 848 wavelength = data2D.source.wavelength 849 center_x = data2D.detector[0].beam_center.x/pixel_width_x 850 center_y = data2D.detector[0].beam_center.y/pixel_width_y 851 681 Pi = math.pi 682 683 # Get the all data & info 684 data = data2D.data 685 err_data = data2D.err_data 686 qx_data = data2D.qx_data 687 qy_data = data2D.qy_data 688 q_data = data2D.q_data 689 690 #set space for 1d outputs 691 x = numpy.zeros(self.nbins) 852 692 y = numpy.zeros(self.nbins) 693 y_err = numpy.zeros(self.nbins) 853 694 y_counts = numpy.zeros(self.nbins) 854 x = numpy.zeros(self.nbins) 855 y_err = numpy.zeros(self.nbins) 856 857 # This If finds qmax within ROI defined by sector lines 858 temp=0 #to find qmax within ROI or phimax and phimin 859 temp0=1000000 860 temp1=0 861 for i in range(numpy.size(data,1)): 862 dx = pixel_width_x*(i+0.5 - center_x) 863 for j in range(numpy.size(data,0)): 864 865 dy = pixel_width_y*(j+0.5 - center_y) 866 q_value = get_q(dx, dy, det_dist, wavelength) 867 # Compute phi and check whether it's within the limits 868 phi_value=math.atan2(dy,dx)+math.pi 869 if self.phi_max>2*math.pi: 870 self.phi_max=self.phi_max-2*math.pi 871 if self.phi_min<0: 872 self.phi_max=self.phi_max+2*math.pi 873 874 #In case of two ROI (symmetric major and minor wings)(for 'q2') 695 696 # Get the min and max into the region: 0 <= phi < 2Pi 697 phi_min = flip_phi(self.phi_min) 698 phi_max = flip_phi(self.phi_max) 699 700 q_data_max = numpy.max(q_data) 701 702 for n in range(len(data)): 703 frac = 0 704 705 # q-value at the pixel (j,i) 706 q_value = q_data[n] 707 708 709 data_n = data[n] 710 711 # Is pixel within range? 712 is_in = False 713 714 # phi-value of the pixel (j,i) 715 phi_value=math.atan2(qy_data[n],qx_data[n])+Pi 716 717 ## No need to calculate the frac when all data are within range 718 if self.r_min <= q_value and q_value <= self.r_max: frac = 1 719 720 if frac == 0: continue 721 722 #In case of two ROIs (symmetric major and minor regions)(for 'q2') 875 723 if run.lower()=='q2': 876 if ((self.phi_max>=0 and self.phi_max<math.pi)and (self.phi_min>=0 and self.phi_min<math.pi)): 877 temp_max=self.phi_max+math.pi 878 temp_min=self.phi_min+math.pi 724 ## For minor sector wing 725 # Calculate the minor wing phis 726 phi_min_minor = flip_phi(phi_min-Pi) 727 phi_max_minor = flip_phi(phi_max-Pi) 728 # Check if phis of the minor ring is within 0 to 2pi 729 if phi_min_minor > phi_max_minor: 730 is_in = (phi_value > phi_min_minor or phi_value < phi_max_minor) 879 731 else: 880 temp_max=self.phi_max 881 temp_min=self.phi_min 882 883 if ((temp_max>=math.pi and temp_max<2*math.pi)and (temp_min>=math.pi and temp_min<2*math.pi)): 884 if (phi_value<temp_min or phi_value>temp_max): 885 if (phi_value<temp_min-math.pi or phi_value>temp_max-math.pi): 886 continue 887 if (self.phi_max<self.phi_min): 888 tmp_max=self.phi_max+math.pi 889 tmp_min=self.phi_min-math.pi 890 else: 891 tmp_max=self.phi_max 892 tmp_min=self.phi_min 893 if (tmp_min<math.pi and tmp_max>math.pi): 894 if((phi_value>tmp_max and phi_value<tmp_min+math.pi)or (phi_value>tmp_max-math.pi and phi_value<tmp_min)): 895 continue 896 #In case of one ROI (major only)(i.e.,for 'q')and do nothing for 'phi'. 897 elif run.lower()=='q': 898 if (self.phi_max>=self.phi_min): 899 if (phi_value<self.phi_min or phi_value>self.phi_max): 900 continue 901 else: 902 if (phi_value<self.phi_min and phi_value>self.phi_max): 903 continue 904 if q_value<qmin or q_value>qmax: 905 continue 906 907 if run.lower()=='phi': 908 if temp1<phi_value: 909 temp1=phi_value 910 if temp0>phi_value: 911 temp0=phi_value 912 913 elif temp<q_value: 914 temp=q_value 915 916 if run.lower()=='phi': 917 self.phi_max=temp1 918 self.phi_min=temp0 919 else: 920 qmax=temp 921 #Beam center is already corrected, but the calculation below assumed it was not. 922 # Thus Beam center shifted back to uncorrected value. ToDo: cleanup the mess. 923 center_x=center_x+0.5 924 center_y=center_y+0.5 925 for i in range(numpy.size(data,1)): 926 dx = pixel_width_x*(i+0.5 - center_x) 927 928 # Min and max x-value for the pixel 929 minx = pixel_width_x*(i - center_x) 930 maxx = pixel_width_x*(i+1.0 - center_x) 931 932 for j in range(numpy.size(data,0)): 933 dy = pixel_width_y*(j+0.5 - center_y) 934 935 q_value = get_q(dx, dy, det_dist, wavelength) 936 937 # Min and max y-value for the pixel 938 miny = pixel_width_y*(j - center_y) 939 maxy = pixel_width_y*(j+1.0 - center_y) 940 941 # Calculate the q-value for each corner 942 # q_[x min or max][y min or max] 943 q_00 = get_q(minx, miny, det_dist, wavelength) 944 q_01 = get_q(minx, maxy, det_dist, wavelength) 945 q_10 = get_q(maxx, miny, det_dist, wavelength) 946 q_11 = get_q(maxx, maxy, det_dist, wavelength) 947 948 # Compute phi and check whether it's within the limits 949 phi_value=math.atan2(dy,dx)+math.pi 950 if self.phi_max>2*math.pi: 951 self.phi_max=self.phi_max-2*math.pi 952 if self.phi_min<0: 953 self.phi_max=self.phi_max+2*math.pi 954 955 # Look for intercept between each side of the pixel 956 # and the constant-q ring for qmax 957 frac_max = get_pixel_fraction(qmax, q_00, q_01, q_10, q_11) 958 959 # Look for intercept between each side of the pixel 960 # and the constant-q ring for qmin 961 frac_min = get_pixel_fraction(qmin, q_00, q_01, q_10, q_11) 962 963 # We are interested in the region between qmin and qmax 964 # therefore the fraction of the surface of the pixel 965 # that we will use to calculate the number of counts to 966 # include is given by: 967 968 frac = frac_max - frac_min 969 970 #In case of two ROI (symmetric major and minor regions)(for 'q2') 971 if run.lower()=='q2': 972 if ((self.phi_max>=0 and self.phi_max<math.pi)and (self.phi_min>=0 and self.phi_min<math.pi)): 973 temp_max=self.phi_max+math.pi 974 temp_min=self.phi_min+math.pi 975 else: 976 temp_max=self.phi_max 977 temp_min=self.phi_min 978 979 if ((temp_max>=math.pi and temp_max<2*math.pi)and (temp_min>=math.pi and temp_min<2*math.pi)): 980 if (phi_value<temp_min or phi_value>temp_max): 981 if (phi_value<temp_min-math.pi or phi_value>temp_max-math.pi): 982 continue 983 if (self.phi_max<self.phi_min): 984 tmp_max=self.phi_max+math.pi 985 tmp_min=self.phi_min-math.pi 986 else: 987 tmp_max=self.phi_max 988 tmp_min=self.phi_min 989 if (tmp_min<math.pi and tmp_max>math.pi): 990 if((phi_value>tmp_max and phi_value<tmp_min+math.pi)or (phi_value>tmp_max-math.pi and phi_value<tmp_min)): 991 continue 992 #In case of one ROI (major only)(i.e.,for 'q' and 'phi') 993 else: 994 if (self.phi_max>=self.phi_min): 995 if (phi_value<self.phi_min or phi_value>self.phi_max): 996 continue 997 998 else: 999 if (phi_value<self.phi_min and phi_value>self.phi_max): 1000 continue 1001 #print "qmax=",qmax,qmin 1002 1003 if q_value<qmin or q_value>qmax: 1004 continue 1005 732 is_in = (phi_value > phi_min_minor and phi_value < phi_max_minor) 733 734 #For all cases(i.e.,for 'q', 'q2', and 'phi') 735 #Find pixels within ROI 736 if phi_min > phi_max: 737 is_in = is_in or (phi_value > phi_min or phi_value < phi_max) 738 else: 739 is_in = is_in or (phi_value>= phi_min and phi_value <phi_max) 740 741 if not is_in: frac = 0 742 if frac == 0: continue 743 1006 744 # Check which type of averaging we need 1007 745 if run.lower()=='phi': 1008 i_bin = int(math.ceil(self.nbins*(phi_value-self.phi_min)/(self.phi_max-self.phi_min))) - 1 746 i_bin = int(math.floor((self.nbins)*(phi_value-self.phi_min)\ 747 /(self.phi_max-self.phi_min))) 1009 748 else: 1010 # If we don't need this pixel, skip the rest of the work 1011 #TODO: an improvement here would be to compute the average 1012 # Q for the pixel from the part that is covered by 1013 # the ring defined by q_min/q_max rather than the complete 1014 # pixel 1015 i_bin = int(math.ceil(self.nbins*(q_value-qmin)/(qmax-qmin))) - 1 1016 1017 try: 1018 y[i_bin] += frac * data[j][i] 1019 except: 1020 import sys 1021 print sys.exc_value 1022 print i_bin, frac 1023 1024 if data2D.err_data == None or data2D.err_data[j][i]==0.0: 1025 y_err[i_bin] += frac * frac * math.fabs(data2D.data[j][i]) 749 i_bin = int(math.floor((self.nbins)*(q_value-self.r_min)/(self.r_max-self.r_min))) 750 751 # Take care of the edge case at phi = 2pi. 752 if i_bin == self.nbins: 753 i_bin = self.nbins -1 754 755 ## Get the total y 756 y[i_bin] += frac * data_n 757 758 if err_data == None or err_data[n] ==0.0: 759 y_err[i_bin] += frac * frac * math.fabs(data_n) 1026 760 else: 1027 y_err[i_bin] += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i]761 y_err[i_bin] += frac * frac * err_data[n]*err_data[n] 1028 762 y_counts[i_bin] += frac 1029 763 764 # Organize the results 1030 765 for i in range(self.nbins): 1031 766 y[i] = y[i] / y_counts[i] 1032 767 y_err[i] = math.sqrt(y_err[i]) / y_counts[i] 1033 # Check which type of averaging we need 1034 if run.lower()=='phi': 1035 #Calculate x[i] and put back the origin of angle back to the right hand side (from the left). 1036 x[i] = ((self.phi_max-self.phi_min)/self.nbins*(1.0*i + 0.5)+self.phi_min-2*math.pi)*180/math.pi 1037 if x[i]<0: 1038 x[i]=180+x[i] 768 769 # The type of averaging: phi,q2, or q 770 # Calculate x[i]should be at the center of the bin 771 if run.lower()=='phi': 772 x[i] = (self.phi_max-self.phi_min)/self.nbins*(1.0*i + 0.5)+self.phi_min 1039 773 else: 1040 x[i] = (qmax-qmin)/self.nbins*(1.0*i + 0.5)+qmin 1041 1042 return Data1D(x=x, y=y, dy=y_err) 774 x[i] = (self.r_max-self.r_min)/self.nbins*(1.0*i + 0.5)+self.r_min 775 776 idx = (numpy.isfinite(y)& numpy.isfinite(y_err)) 777 778 if not idx.any(): 779 raise ValueError, "Average Error: No points inside sector of ROI to average..." 780 elif len(y[idx])!= self.nbins: 781 print "resulted",self.nbins- len(y[idx]),"empty bin(s) due to tight binning..." 782 return Data1D(x=x[idx], y=y[idx], dy=y_err[idx]) 1043 783 1044 784 class SectorPhi(_Sector): … … 1058 798 """ 1059 799 return self._agv(data2D, 'phi') 1060 1061 class SectorQold(_Sector):1062 """1063 Sector average as a function of Q.1064 I(Q) is return and the data is averaged over phi.1065 1066 A sector is defined by r_min, r_max, phi_min, phi_max.1067 The number of bin in Q also has to be defined.1068 """1069 def __call__(self, data2D):1070 """1071 Perform sector average and return I(Q).1072 1073 @param data2D: Data2D object1074 @return: Data1D object1075 """1076 return self._agv(data2D, 'q')1077 800 1078 801 class SectorQ(_Sector):
Note: See TracChangeset
for help on using the changeset viewer.