def simulate_basic_with_pods(ptypy_pars_tree=None, sim_pars=None, save=False): """ Basic Simulation """ p = DEFAULT.copy() ppt = ptypy_pars_tree if ppt is not None: p.update(ppt.get('simulation')) if sim_pars is not None: p.update(sim_pars) P = ptypy.core.Ptycho(ppt, level=1) # make a data source that has is basicaly empty P.datasource = make_sim_datasource(P.modelm, p.pos_drift, p.pos_scale, p.pos_noise) P.modelm.new_data() u.parallel.barrier() P.print_stats() # Propagate and apply psf for simulationg partial coherence (if not done so with modes) for name, pod in P.pods.iteritems(): if not pod.active: continue pod.diff += conv(u.abs2(pod.fw(pod.exit)), p.psf) # Filter storage data similar to a detector. if p.detector is not None: Det = Detector(p.detector) save_dtype = Det.dtype for ID, Sdiff in P.diff.S.items(): # get the mask storage too although their content will be overriden Smask = P.mask.S[ID] dat, mask = Det.filter(Sdiff.data) if p.frame_size is not None: hplanes = u.expect2(p.frame_size) - u.expect2(dat.shape[-2:]) dat = u.crop_pad(dat, hplanes, axes=[-2, -1]).astype(dat.dtype) mask = u.crop_pad(mask, hplanes, axes=[-2, -1]).astype(mask.dtype) Sdiff.fill(dat) Smask.fill(mask) else: save_dtype = None if save: P.modelm.collect_diff_mask_meta(save=save, dtype=save_dtype) u.parallel.barrier() return P
def simulate_basic_with_pods(ptypy_pars_tree=None,sim_pars=None,save=False): """ Basic Simulation """ p = DEFAULT.copy() ppt = ptypy_pars_tree if ppt is not None: p.update(ppt.get('simulation')) if sim_pars is not None: p.update(sim_pars) P = ptypy.core.Ptycho(ppt,level=1) # make a data source that has is basicaly empty P.datasource = make_sim_datasource(P.modelm,p.pos_drift,p.pos_scale,p.pos_noise) P.modelm.new_data() u.parallel.barrier() P.print_stats() # Propagate and apply psf for simulationg partial coherence (if not done so with modes) for name,pod in P.pods.iteritems(): if not pod.active: continue pod.diff += conv(u.abs2(pod.fw(pod.exit)),p.psf) # Filter storage data similar to a detector. if p.detector is not None: Det = Detector(p.detector) save_dtype = Det.dtype for ID,Sdiff in P.diff.S.items(): # get the mask storage too although their content will be overriden Smask = P.mask.S[ID] dat, mask = Det.filter(Sdiff.data) if p.frame_size is not None: hplanes = u.expect2(p.frame_size)-u.expect2(dat.shape[-2:]) dat = u.crop_pad(dat,hplanes,axes=[-2,-1]).astype(dat.dtype) mask = u.crop_pad(mask,hplanes,axes=[-2,-1]).astype(mask.dtype) Sdiff.fill(dat) Smask.fill(mask) else: save_dtype = None if save: P.modelm.collect_diff_mask_meta(save=save,dtype=save_dtype) u.parallel.barrier() return P
def augment_to_coordlist(a, Npos): if np.isscalar(a): a = u.expect2(a) a = np.asarray(a) if a.size % 2 == 0: a = a.reshape(a.size // 2, 2) if a.shape[0] < Npos: b = np.concatenate((1 + Npos // a.shape[0]) * [a], axis=0) else: b = a return b[:Npos, :2]
def augment_to_coordlist(a,Npos): if np.isscalar(a): a=u.expect2(a) a = np.asarray(a) if a.size % 2 == 0: a=a.reshape(a.size//2,2) if a.shape[0] < Npos: b=np.concatenate((1+Npos//a.shape[0])*[a],axis=0) else: b=a return b[:Npos,:2]
def _initialize(self,pars=None,**kwargs): # Starting parameters p=u.Param(DEFAULT) if pars is not None: p.update(pars) for k,v in kwargs.iteritems(): if p.has_key(k): p[k] = v self.p = p self.interact = False # set distance if self.p.z is None or self.p.z==0: raise ValueError('Distance (geometry.z) must not be None or 0') # set frame shape if self.p.N is None or (np.array(self.p.N)==0).any(): raise ValueError('Frame size (geometry.N) must not be None or 0') else: self.p.N = u.expect2(p.N) # Set energy and wavelength if p.energy is None: if p.lam is None: raise ValueError('Wavelength (geometry.lam) and energy (geometry.energy)\n must not both be None') else: self.lam = p.lam # also sets energy else: if p.lam is not None: logger.debug('Energy and wavelength both specified. Energy takes precedence over wavelength') self.energy = p.energy # set initial geometrical misfit to 0 self.p.misfit = u.expect2(0.) # Pixel size self.p.psize_det_is_fix = p.psize_det is not None self.p.psize_sam_is_fix = p.psize_sam is not None if not self.p.psize_det_is_fix and not self.p.psize_sam_is_fix: raise ValueError('Pixel size in sample plane (geometry.psize_sam) and detector plane \n(geometry.psize_det) must not both be None') # fill pixel sizes self.p.psize_sam = u.expect2(p.psize_sam) if self.p.psize_sam_is_fix else u.expect2(1.0) self.p.psize_det = u.expect2(p.psize_det) if self.p.psize_det_is_fix else u.expect2(1.0) # update other values self.update(False) # attach propagator self._propagator = self._get_propagator() self.interact=True
def update(self, geo_pars=None, **kwargs): """ update internal p dictionary. Recompute all internal array buffers """ # local reference to avoid excessive self. use p = self.p if geo_pars is not None: p.update(geo_pars) for k, v in kwargs.iteritems(): if p.has_key(k): p[k] = v # wavelength * distance factor lz = p.lam * p.z #calculate real space pixel size. psize_sam = p.psize_sam if p.psize_sam is not None else lz / p.N / p.psize_det # calculate array shape from misfit self.crop_pad = np.round(u.expect2(p.misfit) / 2.0).astype(int) * 2 self.sh = p.N + self.crop_pad # calculate the grids [X, Y] = u.grids(self.sh, psize_sam, p.origin_sam) [V, W] = u.grids(self.sh, p.psize_det, p.origin_det) # maybe useful later. delete this references if space is short self.grids_sam = [X, Y] self.grids_det = [V, W] # quadratic phase + shift factor before fft pre = np.exp(1j * np.pi * (X**2 + Y**2) / lz).astype(self.dtype) self.pre_fft = pre * np.exp(-2.0 * np.pi * 1j * ( (X - X[0, 0]) * V[0, 0] + (Y - Y[0, 0]) * W[0, 0]) / lz).astype(self.dtype) # quadratic phase + shift factor before fft post = np.exp(1j * np.pi * (V**2 + W**2) / lz).astype(self.dtype) self.post_fft = post * np.exp(-2.0 * np.pi * 1j * (X[0, 0] * V + Y[0, 0] * W) / lz).astype( self.dtype) # factors for inverse operation self.pre_ifft = self.post_fft.conj() self.post_ifft = self.pre_fft.conj()
def update(self,geo_pars=None,**kwargs): """ update internal p dictionary. Recompute all internal array buffers """ # local reference to avoid excessive self. use p = self.p if geo_pars is not None: p.update(geo_pars) for k,v in kwargs.iteritems(): if p.has_key(k): p[k] = v # wavelength * distance factor lz= p.lam * p.z #calculate real space pixel size. psize_sam = p.psize_sam if p.psize_sam is not None else lz / p.N / p.psize_det # calculate array shape from misfit self.crop_pad = np.round(u.expect2(p.misfit) /2.0).astype(int) * 2 self.sh = p.N + self.crop_pad # calculate the grids [X,Y] = u.grids(self.sh,psize_sam,p.origin_sam) [V,W] = u.grids(self.sh,p.psize_det,p.origin_det) # maybe useful later. delete this references if space is short self.grids_sam = [X,Y] self.grids_det = [V,W] # quadratic phase + shift factor before fft pre = np.exp(1j * np.pi * (X**2+Y**2) / lz ).astype(self.dtype) self.pre_fft = pre*np.exp(-2.0*np.pi*1j*((X-X[0,0])*V[0,0]+(Y-Y[0,0])*W[0,0])/ lz).astype(self.dtype) # quadratic phase + shift factor before fft post=np.exp(1j * np.pi * (V**2+W**2) / lz ).astype(self.dtype) self.post_fft = post*np.exp(-2.0*np.pi*1j*(X[0,0]*V+Y[0,0]*W)/ lz).astype(self.dtype) # factors for inverse operation self.pre_ifft = self.post_fft.conj() self.post_ifft = self.pre_fft.conj()
def make_sim_datasource(model_inst, drift=0.0, scale=0.0, noise=0.0): labels = [] sources = [] pars = [] for label, scan in model_inst.scans.items(): source = scan.pars.source if source is None: source = model_inst.ptycho.paths.get_data_file(label=label) labels.append(label) sources.append(None) #p = u.Param() scan_info = u.Param() pos = scan.pos_theory scan_info.positions_theory = pos scan_info.positions = exp_positions(pos, drift, scale, noise) N = u.expect2(scan.pars.geometry.N) scan_info.shape = (len(pos), np.int(N[0]), np.int(N[1])) scan_info.scan_label = label scan_info.data_filename = source pars.append(scan_info) return data.StaticDataSource(sources, pars, labels)
def make_sim_datasource(model_inst,drift=0.0,scale= 0.0,noise=0.0): labels=[] sources =[] pars =[] for label,scan in model_inst.scans.items(): source = scan.pars.source if source is None: source = model_inst.ptycho.paths.get_data_file(label=label) labels.append(label) sources.append(None) #p = u.Param() scan_info=u.Param() pos = scan.pos_theory scan_info.positions_theory = pos scan_info.positions = exp_positions(pos,drift,scale,noise) N = u.expect2(scan.pars.geometry.N) scan_info.shape = (len(pos),np.int(N[0]),np.int(N[1])) scan_info.scan_label = label scan_info.data_filename = source pars.append(scan_info) return data.StaticDataSource(sources,pars,labels)
def read(self, scan=None, **kwargs): """\ Read in the data TODO: (maybe?) MPI to avoid loading all data in a single process for large scans. """ scan=scan if scan is not None else self.p.scan logger.info( 'Processing scan number %s' % str(scan)) self.scan = self.get_nexus_file(scan) logger.debug( 'Data will be read from path: %s' % self.scan) self.exp = load(self.scan,self.nxs.frame) try: self.motors = load(self.scan,self.nxs.motors) except: self.motors=None self.command = load(self.scan,self.nxs.command) self.data = load(self.scan, self.nxs.frame).astype(float) self.label = load(self.scan, self.nxs.label)[0] if self.p.experimentID is None: try: experimentID = load(self.scan, self.nxs.experiment)[0] except: logger.debug('Could not find experiment ID from nexus file %s.' % self.scan) experimentID = os.path.split(base_path[:-1])[1] logger.debug( 'experimentID: "%s" (automatically set).' % experimentID) else: logger.debug( 'experimentID: "%s".' % self.p.experimentID) self.experimentID = self.p.experimentID dpsize = self.p.dpsize ctr = self.p.ctr sh = self.data.shape[-2:] fullframe = False if dpsize is None: dpsize = sh logger.debug( 'Full frames (%d x %d) will be saved (so no recentering).' % (sh)) fullframe = True self.p.dpsize = expect2(dpsize) #data_filename = self.get_save_filename(scan_number, dpsize) #logger.info( 'Data will be saved to %s' % data_filename) f = self.data if not fullframe: # Compute center of mass if self.mask is None: ctr_auto = mass_center(f.sum(0)) else: ctr_auto = mass_center(f.sum(0)*self.mask) print ctr_auto # Check for center position if ctr is None: ctr = ctr_auto logger.debug( 'Using center: (%d, %d)' % (ctr[0],ctr[1])) #elif ctr == 'inter': #import matplotlib as mpl #fig = mpl.pyplot.figure() #ax = fig.add_subplot(1,1,1) #ax.imshow(np.log(f)) #ax.set_title('Select center point (hit return to finish)') #s = u.Multiclicks(ax, True, mode='replace') #mpl.pyplot.show() #s.wait_until_closed() #ctr = np.round(np.array(s.pts[0][::-1])); #logger.debug( 'Using center: (%d, %d) - I would have guessed it is (%d, %d)' % (ctr[0], ctr[1], ctr_auto[0], ctr_auto[1])) else: logger.debug( 'Using center: (%d, %d) - I would have guessed it is (%d, %d)' % (ctr[0], ctr[1], ctr_auto[0], ctr_auto[1])) self.dpsize = dpsize self.ctr = np.array(ctr) lim_inf = -np.ceil(ctr - dpsize/2.).astype(int) lim_sup = np.ceil(ctr + dpsize/2.).astype(int) - np.array(sh) hplane_list = [(lim_inf[0], lim_sup[0]), (lim_inf[1], lim_sup[1])] logger.debug( 'Going from %s to %s (hplane_list = %s)' % (str(sh), str(dpsize), str(hplane_list))) if self.mask is not None: self.mask = u.crop_pad(self.mask, hplane_list).astype(bool) if self.flat is not None: self.flat = u.crop_pad(self.flat, hplane_list,fillpar=1.) if self.dark is not None: self.dark = u.crop_pad(self.dark, hplane_list) if self.data is not None: self.data = u.crop_pad(self.data, hplane_list)
def set_size_probe(self, probe_shape): self.p, self.r = self.parse_params() sh = self.p.scans.savu.data.shape self.probe_size = (1, ) + tuple( u.expect2(sh)) + (self.get_num_probe_modes(), ) print "probe size is" + str(self.probe_size)
def _initialize(self, pars=None, **kwargs): # Starting parameters p = u.Param(DEFAULT) if pars is not None: p.update(pars) for k, v in kwargs.iteritems(): if p.has_key(k): p[k] = v self.p = p self.interact = False # set distance if self.p.z is None or self.p.z == 0: raise ValueError('Distance (geometry.z) must not be None or 0') # set frame shape if self.p.N is None or (np.array(self.p.N) == 0).any(): raise ValueError('Frame size (geometry.N) must not be None or 0') else: self.p.N = u.expect2(p.N) # Set energy and wavelength if p.energy is None: if p.lam is None: raise ValueError( 'Wavelength (geometry.lam) and energy (geometry.energy)\n must not both be None' ) else: self.lam = p.lam # also sets energy else: if p.lam is not None: logger.debug( 'Energy and wavelength both specified. Energy takes precedence over wavelength' ) self.energy = p.energy # set initial geometrical misfit to 0 self.p.misfit = u.expect2(0.) # Pixel size self.p.psize_det_is_fix = p.psize_det is not None self.p.psize_sam_is_fix = p.psize_sam is not None if not self.p.psize_det_is_fix and not self.p.psize_sam_is_fix: raise ValueError( 'Pixel size in sample plane (geometry.psize_sam) and detector plane \n(geometry.psize_det) must not both be None' ) # fill pixel sizes self.p.psize_sam = u.expect2( p.psize_sam) if self.p.psize_sam_is_fix else u.expect2(1.0) self.p.psize_det = u.expect2( p.psize_det) if self.p.psize_det_is_fix else u.expect2(1.0) # update other values self.update(False) # attach propagator self._propagator = self._get_propagator() self.interact = True
def N(self, v): self.p.N[:] = u.expect2(v).astype(int) if self.interact: self.update()
def read(self, scan=None, **kwargs): """\ Read in the data TODO: (maybe?) MPI to avoid loading all data in a single process for large scans. """ scan = scan if scan is not None else self.p.scan logger.info('Processing scan number %s' % str(scan)) self.scan = self.get_nexus_file(scan) logger.debug('Data will be read from path: %s' % self.scan) self.exp = load(self.scan, self.nxs.frame) try: self.motors = load(self.scan, self.nxs.motors) except: self.motors = None self.command = load(self.scan, self.nxs.command) self.data = load(self.scan, self.nxs.frame).astype(float) self.label = load(self.scan, self.nxs.label)[0] if self.p.experimentID is None: try: experimentID = load(self.scan, self.nxs.experiment)[0] except: logger.debug( 'Could not find experiment ID from nexus file %s.' % self.scan) experimentID = os.path.split(base_path[:-1])[1] logger.debug('experimentID: "%s" (automatically set).' % experimentID) else: logger.debug('experimentID: "%s".' % self.p.experimentID) self.experimentID = self.p.experimentID dpsize = self.p.dpsize ctr = self.p.ctr sh = self.data.shape[-2:] fullframe = False if dpsize is None: dpsize = sh logger.debug( 'Full frames (%d x %d) will be saved (so no recentering).' % (sh)) fullframe = True self.p.dpsize = expect2(dpsize) #data_filename = self.get_save_filename(scan_number, dpsize) #logger.info( 'Data will be saved to %s' % data_filename) f = self.data if not fullframe: # Compute center of mass if self.mask is None: ctr_auto = mass_center(f.sum(0)) else: ctr_auto = mass_center(f.sum(0) * self.mask) print ctr_auto # Check for center position if ctr is None: ctr = ctr_auto logger.debug('Using center: (%d, %d)' % (ctr[0], ctr[1])) #elif ctr == 'inter': #import matplotlib as mpl #fig = mpl.pyplot.figure() #ax = fig.add_subplot(1,1,1) #ax.imshow(np.log(f)) #ax.set_title('Select center point (hit return to finish)') #s = u.Multiclicks(ax, True, mode='replace') #mpl.pyplot.show() #s.wait_until_closed() #ctr = np.round(np.array(s.pts[0][::-1])); #logger.debug( 'Using center: (%d, %d) - I would have guessed it is (%d, %d)' % (ctr[0], ctr[1], ctr_auto[0], ctr_auto[1])) else: logger.debug( 'Using center: (%d, %d) - I would have guessed it is (%d, %d)' % (ctr[0], ctr[1], ctr_auto[0], ctr_auto[1])) self.dpsize = dpsize self.ctr = np.array(ctr) lim_inf = -np.ceil(ctr - dpsize / 2.).astype(int) lim_sup = np.ceil(ctr + dpsize / 2.).astype(int) - np.array(sh) hplane_list = [(lim_inf[0], lim_sup[0]), (lim_inf[1], lim_sup[1])] logger.debug('Going from %s to %s (hplane_list = %s)' % (str(sh), str(dpsize), str(hplane_list))) if self.mask is not None: self.mask = u.crop_pad(self.mask, hplane_list).astype(bool) if self.flat is not None: self.flat = u.crop_pad(self.flat, hplane_list, fillpar=1.) if self.dark is not None: self.dark = u.crop_pad(self.dark, hplane_list) if self.data is not None: self.data = u.crop_pad(self.data, hplane_list)
def psize_sam(self, v): """ changing source space pixel size """ self.p.psize_sam[:] = u.expect2(v) if self.interact: self.update()
def psize_det(self, v): """ changing propagated space pixel size """ self.p.psize_det[:] = u.expect2(v) if self.interact: self.update()
def prepare(self, scan=None, filename=None, dtype=np.uint32, **kwargs): self.p.update( kwargs) #rebin = rebin if rebin is not None else self.p.rebin scan = scan if scan is not None else self.p.scan self.read(scan, **kwargs) DS = u.Param() dark = self.dark data = self.data if dark is not None: if dark.ndim == 3: dark = dark.mean(0) dark = np.resize(dark, data.shape) flat = self.flat if flat is not None: if flat.ndim == 3: flat = flat.mean(0) flat = np.resize(flat, self.data.shape) #plt.ion(); #plt.figure();plt.imshow(dark[0]);plt.colorbar() #plt.figure();plt.imshow((flat-dark)[0]);plt.colorbar() #plt.figure();plt.imshow(data[0]);plt.colorbar() if flat is not None and dark is not None: data = (data - dark) / (flat - dark) elif dark is not None: data = data - dark else: data = data # remove negative values data[data < 0] = 0 # #plt.figure();plt.imshow(DS.data[0],vmin=0);plt.colorbar() # if self.mask is None: mask = np.ones_like(data, dtype=np.bool) # #DS.flat = self.flat #DS.dark = self.dark DS.scan_info = u.Param() s = DS.scan_info p = self.p #s.scan_number = p.scan_number s.scan_label = 'S' + self.label #'S%05d' % p.scan_number s.data_filename = self.scan #scandict['data_filename'] s.wavelength = u.keV2m(p.energy) s.energy = p.energy rebin = self.p.rebin s.detector_pixel_size = p.detector_pixel_size * rebin if p.detector_pixel_size is not None else None p.dpsize = p.dpsize / rebin s.detector_distance = p.detector_distance s.initial_ctr = self.ctr / rebin if rebin != 1: sh = data.shape data = u.rebin(data, sh[0], sh[1] / rebin, sh[2] / rebin) mask = u.rebin(mask.astype(int), sh[0], sh[1] / rebin, sh[2] / rebin).astype(bool) data = flip(data, self.p.flip) mask = flip(mask, self.p.flip) DS.data = data.astype(dtype) DS.mask = mask DS.data[np.invert(DS.mask)] = 0 #s.date_collected = scandict['date'] s.date_processed = time.asctime() s.exposure_time = self.exp #if meta is not None: s.raw_filenames = meta['filename'] s.preparation_basepath = self.base_path s.preparation_other = {} s.shape = DS.data.shape s.positions_theory = None s.scan_command = self.command motors = p.motors if self.motors is not None: Nmotors = len(motors) logger.debug('Motors are : %s' % str(p.motors)) mmult = u.expect2(p.motors_multiplier) pos_list = [ mmult[i] * np.array(self.motors[motors[i]]) for i in range(Nmotors) ] s.positions = np.array(pos_list).T else: s.positions = None self.p.scan_label = s.scan_label if filename is None: p.write_path = WRITE_PATH_PATTERN.format(**p) filename = SAVE_FILENAME_PATTERN.format(**p) s.data_filename = u.clean_path(filename) io.h5write(filename, DS) return DS
def prepare(self,scan=None,filename=None,dtype=np.uint32,**kwargs): self.p.update(kwargs) #rebin = rebin if rebin is not None else self.p.rebin scan = scan if scan is not None else self.p.scan self.read( scan, **kwargs) DS = u.Param() dark = self.dark data = self.data if dark is not None: if dark.ndim == 3: dark = dark.mean(0) dark = np.resize(dark,data.shape) flat = self.flat if flat is not None: if flat.ndim == 3: flat = flat.mean(0) flat = np.resize(flat,self.data.shape) #plt.ion(); #plt.figure();plt.imshow(dark[0]);plt.colorbar() #plt.figure();plt.imshow((flat-dark)[0]);plt.colorbar() #plt.figure();plt.imshow(data[0]);plt.colorbar() if flat is not None and dark is not None: data = (data-dark )/(flat-dark) elif dark is not None: data = data - dark else: data = data # remove negative values data[data<0]=0 # #plt.figure();plt.imshow(DS.data[0],vmin=0);plt.colorbar() # if self.mask is None: mask = np.ones_like(data,dtype=np.bool) # #DS.flat = self.flat #DS.dark = self.dark DS.scan_info = u.Param() s = DS.scan_info p = self.p #s.scan_number = p.scan_number s.scan_label = 'S'+self.label #'S%05d' % p.scan_number s.data_filename = self.scan #scandict['data_filename'] s.wavelength = u.keV2m( p.energy ) s.energy = p.energy rebin = self.p.rebin s.detector_pixel_size = p.detector_pixel_size * rebin if p.detector_pixel_size is not None else None p.dpsize = p.dpsize / rebin s.detector_distance = p.detector_distance s.initial_ctr = self.ctr / rebin if rebin!=1: sh = data.shape data = u.rebin(data,sh[0],sh[1]/rebin,sh[2]/rebin) mask = u.rebin(mask.astype(int),sh[0],sh[1]/rebin,sh[2]/rebin).astype(bool) data = flip(data,self.p.flip) mask = flip(mask,self.p.flip) DS.data = data.astype(dtype) DS.mask = mask DS.data[np.invert(DS.mask)]=0 #s.date_collected = scandict['date'] s.date_processed = time.asctime() s.exposure_time = self.exp #if meta is not None: s.raw_filenames = meta['filename'] s.preparation_basepath = self.base_path s.preparation_other = {} s.shape = DS.data.shape s.positions_theory = None s.scan_command = self.command motors = p.motors if self.motors is not None: Nmotors = len(motors) logger.debug( 'Motors are : %s' % str(p.motors)) mmult = u.expect2(p.motors_multiplier) pos_list = [mmult[i]*np.array(self.motors[motors[i]]) for i in range(Nmotors)] s.positions = np.array(pos_list).T else: s.positions = None self.p.scan_label = s.scan_label if filename is None: p.write_path = WRITE_PATH_PATTERN.format(**p) filename = SAVE_FILENAME_PATTERN.format(**p) s.data_filename = u.clean_path(filename) io.h5write(filename,DS) return DS
def N(self,v): self.p.N[:] = u.expect2(v).astype(int) if self.interact: self.update()
def psize_det(self,v): """ changing propagated space pixel size """ self.p.psize_det[:] = u.expect2(v) if self.interact: self.update()
def psize_sam(self,v): """ changing source space pixel size """ self.p.psize_sam[:] = u.expect2(v) if self.interact: self.update()