Changeset 883a2ef in sasview for sansrealspace/src/realspace


Ignore:
Timestamp:
Nov 28, 2007 10:25:16 AM (17 years ago)
Author:
Mathieu Doucet <doucetm@…>
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:
aa61e49
Parents:
f980d4a
Message:

Updated according to code review.
Fixed consecutive 2D sims.

Location:
sansrealspace/src/realspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • sansrealspace/src/realspace/VolumeCanvas.py

    ra2c1196 r883a2ef  
    11#!/usr/bin/env python 
    22""" Volume Canvas 
    3     Simulation canvas 
     3 
     4    Simulation canvas for real-space simulation of SANS scattering intensity. 
     5    The user can create an arrangement of basic shapes and estimate I(q) and 
     6    I(q_x, q_y). Error estimates on the simulation are also available.  
     7     
     8    Example: 
     9     
     10    import sans.realspace.VolumeCanvas as VolumeCanvas 
     11    canvas = VolumeCanvas.VolumeCanvas() 
     12    canvas.setParam('lores_density', 0.01) 
     13     
     14    sphere = SphereDescriptor() 
     15    handle = canvas.addObject(sphere) 
     16 
     17    output, error = canvas.getIqError(q=0.1) 
     18    output, error = canvas.getIq2DError(0.1, 0.1) 
     19     
     20    or alternatively: 
     21    iq = canvas.run(0.1) 
     22    i2_2D = canvas.run([0.1, 1.57]) 
     23     
    424""" 
    525 
    626from sans.models.BaseComponent import BaseComponent 
    7 from sansModeling.pointsmodelpy import pointsmodelpy 
    8 from sansModeling.geoshapespy import geoshapespy 
     27from sans.simulation.pointsmodelpy import pointsmodelpy 
     28from sans.simulation.geoshapespy import geoshapespy 
    929 
    1030import os.path, math 
     
    1333    """ 
    1434        Class to hold the information about a shape 
     35        The descriptor holds a dictionary of parameters. 
     36         
     37        Note: if shape parameters are accessed directly 
     38        from outside VolumeCanvas. The getPr method 
     39        should be called before evaluating I(q). 
     40                 
    1541    """ 
    1642    def __init__(self): 
     
    4874    """ 
    4975        Descriptor for a sphere 
     76         
     77        The parameters are: 
     78            - radius [Angstroem] [default = 20 A] 
     79            - Contrast [A-2] [default = 1 A-2] 
     80             
    5081    """ 
    5182    def __init__(self): 
     
    5687        # Default parameters 
    5788        self.params["type"]   = "sphere" 
     89        # Radius of the sphere 
    5890        self.params["radius"] = 20.0 
     91        # Constrast parameter 
    5992        self.params["contrast"] = 1.0 
    6093 
     
    74107        Descriptor for a cylinder 
    75108        Orientation: Default cylinder is along Y 
     109         
     110        Parameters: 
     111            - Length [default = 40 A] 
     112            - Radius [default = 10 A] 
     113            - Contrast [default = 1 A-2] 
    76114    """ 
    77115    def __init__(self): 
     
    82120        # Default parameters 
    83121        self.params["type"]   = "cylinder" 
     122        # Length of the cylinder 
    84123        self.params["length"] = 40.0 
     124        # Radius of the cylinder 
    85125        self.params["radius"] = 10.0 
     126        # Constrast parameter 
    86127        self.params["contrast"] = 1.0 
    87128         
     
    101142    """ 
    102143        Descriptor for an ellipsoid 
     144         
     145        Parameters: 
     146            - Radius_x along the x-axis [default = 30 A] 
     147            - Radius_y along the y-axis [default = 20 A] 
     148            - Radius_z along the z-axis [default = 10 A] 
     149            - contrast [default = 1 A-2] 
    103150    """ 
    104151    def __init__(self): 
     
    129176    """ 
    130177        Descriptor for an helix 
     178         
     179        Parameters: 
     180            -radius_helix: the radius of the helix [default = 10 A] 
     181            -radius_tube: radius of the "tube" that forms the helix [default = 3 A] 
     182            -pitch: distance between two consecutive turns of the helix [default = 34 A] 
     183            -turns: number of turns of the helix [default = 3] 
     184            -contrast: contrast parameter [default = 1 A-2] 
    131185    """ 
    132186    def __init__(self): 
     
    158212    """ 
    159213        Descriptor for a PDB set of points 
     214         
     215        Parameter: 
     216            - file = name of the PDB file 
    160217    """ 
    161218    def __init__(self, filename): 
     
    192249        Class representing an empty space volume to add  
    193250        geometrical object to. 
     251         
     252        For 1D I(q) simulation, getPr() is called internally for the 
     253        first call to getIq(). 
     254         
    194255    """ 
    195256     
     
    213274        self.npts = 0 
    214275        self.hasPr = False         
     276         
     277    def _model_changed(self): 
     278        """ 
     279            Reset internal data members to reflect the fact that the  
     280            real-space model has changed 
     281        """ 
     282        self.hasPr  = False 
     283        self.points = None 
    215284         
    216285    def addObject(self, shapeDesc, id = None): 
     
    234303 
    235304        #model changed, need to recalculate P(r) 
    236         self.hasPr = False 
     305        self._model_changed() 
    237306 
    238307        return id 
     
    247316            could be called. If multiple shapes are involved, then  
    248317            simulation has to be performed. 
     318             
     319            This function is deprecated, use addObject(). 
    249320         
    250321            @param shape: name of the object to add to the canvas [string] 
     
    265336            raise ValueError, "VolumeCanvas.add: Unknown shape %s" % shape 
    266337         
    267         # Self the order number 
    268         shapeDesc.params['order'] = self.shapecount 
    269         # Store the shape in a dictionary entry associated 
    270         # with the handle 
    271         self.shapes[id] = shapeDesc 
    272         self.shapecount += 1 
    273  
    274         #model changed, need to recalculate P(r) 
    275         self.hasPr = False 
    276  
    277         return id 
     338        return self.addObject(shapeDesc, id) 
    278339 
    279340    def delete(self, id): 
     
    289350 
    290351        #model changed, need to recalculate P(r) 
    291         self.hasPr = False 
     352        self._model_changed() 
    292353 
    293354 
    294355    def setParam(self, name, value):     
    295356        """ 
     357            Function to set the value of a parameter.  
     358            Both VolumeCanvas parameters and shape parameters 
     359            are accessible.  
     360             
     361            Note: if shape parameters are accessed directly 
     362            from outside VolumeCanvas. The getPr method 
     363            should be called before evaluating I(q). 
     364         
     365            TODO: implemented a check method to protect 
     366            against that. 
     367         
    296368            @param name: name of the parameter to change 
    297369            @param value: value to give the parameter 
     
    312384                    # The parameter was found, now change it 
    313385                    self.shapes[toks[0]].params[toks[1]] = value 
    314                     self.hasPr = False 
     386                    self._model_changed() 
    315387                else: 
    316388                    raise ValueError, "Could not find parameter %s" % name 
     
    322394            # shape, see if the parameter is part of this object 
    323395            BaseComponent.setParam(self, name, value) 
    324             self.hasPr = False 
     396            self._model_changed() 
    325397 
    326398    def getParam(self, name):     
     
    412484        return self.shapes.keys() 
    413485 
    414     def addSingleShape(self, shapeDesc): 
     486    def _addSingleShape(self, shapeDesc): 
    415487        """ 
    416488            create shapeobject based on shapeDesc 
     
    425497                shapeDesc.shapeObject, shapeDesc.params['contrast'])   
    426498 
    427     def createVolumeFromList(self): 
     499    def _createVolumeFromList(self): 
    428500        """ 
    429501            Create a new lores model with all the shapes in our internal list 
     
    469541        for i in range(len_list-1, -1, -1): 
    470542            shapedesc = self.shapes[obj_list[i][1]] 
    471             self.addSingleShape(shapedesc) 
     543            self._addSingleShape(shapedesc) 
    472544 
    473545        return 0      
     
    475547    def getPr(self): 
    476548        """ 
    477             Calculate P(r) 
     549            Calculate P(r) from the objects on the canvas. 
     550            This method should always be called after the shapes 
     551            on the VolumeCanvas have changed. 
     552             
    478553            @return: calculation output flag  
    479554        """ 
     
    483558        # If there are not shapes, do nothing 
    484559        if len(self.shapes) == 0: 
    485             self.hasPr = False 
     560            self._model_changed() 
    486561            return 0 
    487562         
    488563        # generate space filling points from shape list 
    489         self.createVolumeFromList() 
     564        self._createVolumeFromList() 
    490565 
    491566        self.points = pointsmodelpy.new_point3dvec() 
     
    553628    def _create_modelObject(self): 
    554629        """ 
    555             Returns simulate I(q) for given q_x and q_y values. 
    556             Also returns model object 
    557             @param qx: q_x [A-1] 
    558             @param qy: q_y [A-1] 
    559             @return: I(q) [cm-1], model object 
     630            Create the simulation model obejct from the list 
     631            of shapes. 
     632             
     633            This method needs to be called each time a parameter 
     634            changes because of the way the underlying library 
     635            was (badly) written. It is impossible to change a  
     636            parameter, or remove a shape without having to  
     637            refill the space points. 
     638             
     639            TODO: improve that. 
    560640        """ 
    561641        # To find a complete example of the correct call order: 
     
    564644        # If there are not shapes, do nothing 
    565645        if len(self.shapes) == 0: 
    566             self.hasPr = False 
     646            self._model_changed() 
    567647            return 0 
    568648         
    569649        # generate space filling points from shape list 
    570         self.createVolumeFromList() 
     650        self._createVolumeFromList() 
    571651 
    572652        self.points = pointsmodelpy.new_point3dvec() 
     
    590670            @return: I(q) [cm-1] 
    591671        """ 
    592         self._create_modelObject() 
    593                  
     672         
     673        # If this is the first simulation call, we need to generate the 
     674        # space points 
     675        if self.points == None: 
     676            self._create_modelObject() 
     677             
     678            # Protect against empty model 
     679            if self.points == None: 
     680                return 0 
     681                
     682        # Evalute I(q)  
    594683        norm =  1.0e8/self.params['lores_density']*self.params['scale'] 
    595684        return norm*pointsmodelpy.get_complex_iq_2D(self.complex_model, self.points, qx, qy)\ 
     
    671760            uncertainty. 
    672761             
    673             @param q: q-value [float] 
     762            @param qx: qx-value [float] 
     763            @param qy: qy-value [float] 
    674764            @return: mean, error [float, float] 
    675765        """ 
  • sansrealspace/src/realspace/__init__.py

    r1141c5d r883a2ef  
    2222# 
    2323# \subsection depends External Dependencies 
    24 # You have to have the DANSE distutils-adpt package installed: 
    25 # \verbatime 
    26 #$ svn co svn://danse.us/distutils-adpt 
    27 # \endverbatim 
     24# None 
    2825# 
    2926# \subsection build Building the code 
     
    6158# To add an object: 
    6259# \verbatim 
    63 #    handle = canvas.add('sphere') 
     60#    sphare = VolumeCanvas.SphereDescriptor() 
     61#    handle = canvas.addObject(sphere) 
    6462#    canvas.setParam('%s.radius' % handle, 15.0) 
    6563# \endverbatim 
     
    6866# \verbatim 
    6967#    output, error = canvas.getIqError(q=0.1) 
     68#    output, error = canvas.getIq2DError(qx=0.1, qy=0.1) 
    7069# \endverbatim 
    7170# 
  • sansrealspace/src/realspace/test/cylinder_d=0.5_Iq2D.txt

    rf980d4a r883a2ef  
    11PARS: {'scale': 1.0, 'length': 100, 'radius': 20, 'background': 0.0, 'cyl_theta': 1.5707963267948966, 'contrast': 1.0, 'cyl_phi': 1.5707963267948966} 
    22<q>  <ana>  <sim>  <err> 
    3 0.001  1.25586e+013  1.25584e+013  5.25262e+008 
    4 0.00929167  1.1909e+013  1.19058e+013  1.05064e+010 
    5 0.0175833  1.0341e+013  1.03345e+013  3.12179e+010 
    6 0.025875  8.16205e+012  8.14926e+012  5.17962e+010 
    7 0.0341667  5.77306e+012  5.81045e+012  6.21145e+010 
    8 0.0424583  3.56425e+012  3.55223e+012  5.90114e+010 
    9 0.05075  1.82415e+012  1.80424e+012  4.48859e+010 
    10 0.0590417  6.86403e+011  6.93632e+011  2.71769e+010 
    11 0.0673333  1.26379e+011  1.2136e+011  1.06077e+010 
    12 0.075625  1.69416e+009  1.50569e+009  1.08773e+009 
    13 0.0839167  1.17674e+011  1.24732e+011  9.32509e+009 
    14 0.0922083  2.93262e+011  2.7841e+011  1.38067e+010 
    15 0.1005  4.06932e+011  4.09882e+011  1.72092e+010 
    16 0.108792  4.1248e+011  4.37694e+011  1.84369e+010 
    17 0.117083  3.26735e+011  3.07555e+011  1.59575e+010 
    18 0.125375  2.00372e+011  1.98719e+011  1.30112e+010 
    19 0.133667  8.63351e+010  8.31996e+010  8.33716e+009 
    20 0.141958  1.76833e+010  1.4757e+010  3.47028e+009 
    21 0.15025  2.29778e+008  5.88028e+008  6.83052e+008 
    22 0.158542  1.83678e+010  1.6151e+010  3.56511e+009 
    23 0.166833  4.78555e+010  5.04122e+010  6.33775e+009 
    24 0.175125  6.83196e+010  7.36705e+010  7.69267e+009 
    25 0.183417  7.03999e+010  7.70008e+010  7.86228e+009 
    26 0.191708  5.61199e+010  5.68128e+010  6.74312e+009 
    27 0.2  3.43293e+010  3.12432e+010  4.97778e+009 
     30.001  1.25586e+013  1.25584e+013  5.24372e+008 
     40.00929167  1.1909e+013  1.19119e+013  1.04128e+010 
     50.0175833  1.0341e+013  1.03444e+013  3.11005e+010 
     60.025875  8.16205e+012  8.19485e+012  5.13766e+010 
     70.0341667  5.77306e+012  5.76297e+012  6.22366e+010 
     80.0424583  3.56425e+012  3.54391e+012  5.90911e+010 
     90.05075  1.82415e+012  1.8406e+012  4.53958e+010 
     100.0590417  6.86403e+011  6.94445e+011  2.73011e+010 
     110.0673333  1.26379e+011  1.26541e+011  1.08456e+010 
     120.075625  1.69416e+009  1.95158e+009  1.23535e+009 
     130.0839167  1.17674e+011  1.26397e+011  9.39118e+009 
     140.0922083  2.93262e+011  2.85994e+011  1.40496e+010 
     150.1005  4.06932e+011  4.13645e+011  1.72159e+010 
     160.108792  4.1248e+011  4.28788e+011  1.82404e+010 
     170.117083  3.26735e+011  3.25064e+011  1.63836e+010 
     180.125375  2.00372e+011  1.90569e+011  1.27255e+010 
     190.133667  8.63351e+010  8.94079e+010  8.63641e+009 
     200.141958  1.76833e+010  1.23431e+010  3.16684e+009 
     210.15025  2.29778e+008  1.37597e+008  3.31662e+008 
     220.158542  1.83678e+010  2.03592e+010  4.03062e+009 
     230.166833  4.78555e+010  4.76265e+010  6.15775e+009 
     240.175125  6.83196e+010  6.19958e+010  7.01335e+009 
     250.183417  7.03999e+010  7.12558e+010  7.51039e+009 
     260.191708  5.61199e+010  5.79624e+010  6.79382e+009 
     270.2  3.43293e+010  3.93938e+010  5.56512e+009 
  • sansrealspace/src/realspace/test/simulation_stimuli.py

    r8c050c1 r883a2ef  
    4646    def setup(self): 
    4747        """Setup the canvas for stimuli application""" 
    48         return VolumeCanvas.VolumeCanvas() 
     48        volume = VolumeCanvas.VolumeCanvas() 
     49        volume.params['lores_density'] = 0.05 
     50        return volume 
    4951     
    5052    def getRandomStimulus(self): 
  • sansrealspace/src/realspace/test/utest_oriented.py

    rf980d4a r883a2ef  
    434434            raise sys.exc_type, sys.exc_value 
    435435 
    436            
     436class TestParamChange(unittest.TestCase): 
     437    """ Tests for oriented (2D) systems """ 
     438         
     439    def setUp(self): 
     440        """ Set up cylinder model """ 
     441        from sans.models.CylinderModel import CylinderModel 
     442        radius = 5 
     443        length = 40 
     444        density = 20 
     445     
     446        # Analytical model 
     447        self.ana = CylinderModel() 
     448        self.ana.setParam('scale', 1.0) 
     449        self.ana.setParam('contrast', 1.0) 
     450        self.ana.setParam('background', 0.0) 
     451        self.ana.setParam('radius', radius) 
     452        self.ana.setParam('length', length) 
     453        self.ana.setParam('cyl_theta', math.pi/2.0) 
     454        self.ana.setParam('cyl_phi', math.pi/2.0) 
     455     
     456        # Simulation model 
     457        self.model = VolumeCanvas.VolumeCanvas() 
     458        self.handle = self.model.add('cylinder') 
     459        self.model.setParam('lores_density', density) 
     460        self.model.setParam('%s.radius' % self.handle, radius) 
     461        self.model.setParam('%s.length' % self.handle, length) 
     462        self.model.setParam('scale' , 1.0) 
     463        self.model.setParam('%s.contrast' % self.handle, 1.0) 
     464        self.model.setParam('background' , 0.0) 
     465        self.model.setParam('%s.orientation' % self.handle, [0,0,0]) 
     466     
     467    def testalongY(self): 
     468        """ Test that a parameter change forces the generation 
     469            of new space points 
     470        """ 
     471        ana_val = self.ana.runXY([0.1, 0.2]) 
     472        sim_val = self.model.getIq2D(0.1, 0.2) 
     473         
     474        self.assert_( math.fabs(sim_val/ana_val-1.0)<0.05 ) 
     475         
     476        # Change the radius a re-evaluate 
     477        self.ana.setParam('radius', 10) 
     478        self.model.setParam('%s.radius' % self.handle, 10) 
     479         
     480        ana_val = self.ana.runXY([0.1, 0.2]) 
     481        sim_val = self.model.getIq2D(0.1, 0.2) 
     482        self.assert_( math.fabs(sim_val/ana_val-1.0)<0.05 ) 
    437483 
    438484 
Note: See TracChangeset for help on using the changeset viewer.