Changeset f4a1433 in sasview for src/sas/sasgui/perspectives/calculator
- Timestamp:
- Oct 24, 2017 12:44:26 AM (8 years ago)
- Branches:
- 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
- Children:
- fca1f50, d6b234b
- Parents:
- 16afe01 (diff), 5582b078 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Location:
- src/sas/sasgui/perspectives/calculator
- Files:
-
- 22 added
- 22 deleted
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sasgui/perspectives/calculator/__init__.py
r959eb01 r5a405bd 18 18 path = os.path.dirname(__file__) 19 19 #Look for maximum n_dir up of the current dir to find media 20 20 21 21 #for i in range(n_dir): 22 22 i = 0 … … 30 30 return media_path 31 31 i += 1 32 32 33 33 raise RuntimeError('Could not find calculator media files') 34 34 … … 36 36 """ 37 37 Return the data files associated with media calculator. 38 38 39 39 The format is a list of (directory, [files...]) pairs which can be 40 40 used directly in setup(...,data_files=...) for setup.py. … … 42 42 """ 43 43 data_files = [] 44 path = get_data_path(media="media") 45 for f in findall(path): 46 data_files.append(('media/calculator_media', [f])) 44 data_files.append(('media/calculator_media', findall(get_data_path("media")))) 47 45 return data_files -
src/sas/sasgui/perspectives/calculator/image_viewer.py
ra1b8fee r412e9e8b 59 59 _, extension = os.path.splitext(basename) 60 60 try: 61 # Note that matplotlib only reads png natively. 62 # Any other formats (tiff, jpeg, etc) are passed 63 # to PIL which seems to have a problem in version 64 # 1.1.7 that causes a close error which shows up in 65 # the log file. This does not seem to have any adverse 66 # effects. PDB --- September 17, 2017. 61 67 img = mpimg.imread(file_path) 62 68 is_png = extension.lower() == '.png' … … 89 95 if location is None: 90 96 location = os.getcwd() 91 dlg = wx.FileDialog(self.parent, "Image Viewer: Choose a image file", 92 location, "", "", style=wx.FD_OPEN | wx.FD_MULTIPLE) 97 wildcard="Images (*.bmp;*.gif;*jpeg,*jpg;*.png;*tif;*.tiff)|*bmp;\ 98 *.gif; *.jpg; *.jpeg;*png;*.png;*.tif;*.tiff|"\ 99 "Bitmap (*.bmp)|*.bmp|"\ 100 "GIF (*.gif)|*.gif|"\ 101 "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|"\ 102 "PNG (*.png)|*.png|"\ 103 "TIFF (*.tif;*.tiff)|*.tif;*tiff|"\ 104 "All Files (*.*)|*.*|" 105 106 dlg = wx.FileDialog(self.parent, "Image Viewer: Choose an image file", 107 location, "", wildcard, style=wx.FD_OPEN 108 | wx.FD_MULTIPLE) 93 109 if dlg.ShowModal() == wx.ID_OK: 94 110 path = dlg.GetPaths() -
src/sas/sasgui/perspectives/calculator/media/density_calculator_help.rst
rd85c194 r6aad2e8 29 29 4) Click the 'Calculate' button to perform the calculation. 30 30 31 .. image:: density_tutor. gif31 .. image:: density_tutor.png 32 32 33 33 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ -
src/sas/sasgui/perspectives/calculator/media/gen_sas_help.html
rd85c194 r6aad2e8 19 19 by the particle 20 20 <p> 21 <img src="gen_i. gif"/>21 <img src="gen_i.png"/> 22 22 </p> 23 23 <br> … … 26 26 of the j'th pixel respectively. And the total volume 27 27 <p> 28 <img src="v_j. gif"/>28 <img src="v_j.png"/> 29 29 </p> 30 30 <br> … … 44 44 scattering length. (Figure below). 45 45 <p> 46 <img src="mag_vector. bmp"/>46 <img src="mag_vector.png"/> 47 47 </p> 48 48 <br> 49 49 The magnetic scattering length density is then 50 50 <p> 51 <img src="dm_eq. gif"/>51 <img src="dm_eq.png"/> 52 52 </p> 53 53 <br> … … 66 66 <br> 67 67 <p> 68 <img src="gen_mag_pic. bmp"/>68 <img src="gen_mag_pic.png"/> 69 69 </p> 70 70 <br> … … 75 75 densities , including the nuclear scattering length density (β <sub>N</sub>) are given as, for non-spin-flips, 76 76 <p> 77 <img src="sld1. gif"/>77 <img src="sld1.png"/> 78 78 </p> 79 79 <br> … … 81 81 for spin-flips, 82 82 <p> 83 <img src="sld2. gif"/>83 <img src="sld2.png"/> 84 84 </p> 85 85 <br> … … 87 87 where 88 88 <p> 89 <img src="mxp. gif"/>89 <img src="mxp.png"/> 90 90 </p> 91 91 <p> 92 <img src="myp. gif"/>92 <img src="myp.png"/> 93 93 </p> 94 94 <p> 95 <img src="mzp. gif"/>95 <img src="mzp.png"/> 96 96 </p> 97 97 <p> 98 <img src="mqx. gif"/>98 <img src="mqx.png"/> 99 99 </p> 100 100 <p> 101 <img src="mqy. gif"/>101 <img src="mqy.png"/> 102 102 </p> 103 103 <br> … … 110 110 <br> 111 111 <p> 112 <img src="gen_gui_help. bmp"/>112 <img src="gen_gui_help.png"/> 113 113 </p> 114 114 <br> … … 136 136 in a 2D output, whileas the scattering calculation averaged over all the orientations uses the Debye equation providing a 1D output: 137 137 <p> 138 <img src="gen_debye_eq. gif"/>138 <img src="gen_debye_eq.png"/> 139 139 </p> 140 140 <br> -
src/sas/sasgui/perspectives/calculator/media/image_viewer_help.rst
rda456fb r412e9e8b 34 34 will be displayed. 35 35 36 .. image:: load_image. bmp36 .. image:: load_image.png 37 37 38 38 3) To save, print, or copy the image, or to apply a grid overlay, right-click 39 39 anywhere in the plot. 40 40 41 .. image:: pic_plot. bmp41 .. image:: pic_plot.png 42 42 43 43 4. If the image is taken from a 2D detector, SasView can attempt to convert … … 51 51 then click the OK. 52 52 53 .. image:: pic_convert. bmp53 .. image:: pic_convert.png 54 54 55 55 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ -
src/sas/sasgui/perspectives/calculator/media/kiessig_calculator_help.rst
r7805458 r5ed76f8 10 10 ----------- 11 11 12 This tool is approximately estimates the thickness of a layer or the diameter13 of particles from the position of the Kiessig fringe/Bragg peak in NR/SAS data 14 usingthe relation12 This tool estimates real space dimensions from the position or spacing of 13 features in recipricol space. In particular a particle of size $d$ will 14 give rise to Bragg peaks with spacing $\Delta q$ according to the relation 15 15 16 (thickness *or* size) = 2 * |pi| / (fringe_width *or* peak position) 17 16 .. math:: 17 18 d = 2\pi / \Delta q 19 20 Similarly, the spacing between the peaks in Kiessig fringes in reflectometry 21 data arise from layers of thickness $d$. 22 18 23 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 19 24 … … 21 26 -------------- 22 27 23 To get a rough thickness or particle size, simply type the fringe or peak 28 To get a rough thickness or particle size, simply type the fringe or peak 24 29 position (in units of 1/|Ang|\) and click on the *Compute* button. 25 30 26 31 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 27 32 28 .. note:: This help document was last changed by Steve King, 01May2015 29 33 .. note:: This help document was last changed by Paul Kienzle, 05Apr2017 -
src/sas/sasgui/perspectives/calculator/media/resolution_calculator_help.rst
r7805458 r5ed76f8 10 10 ----------- 11 11 12 This tool is approximately estimates the resolution of Q from SAS instrumental13 parameter values assuming that the detector is flat and normal to the 12 This tool is approximately estimates the resolution of $Q$ from SAS instrumental 13 parameter values assuming that the detector is flat and normal to the 14 14 incident beam. 15 15 … … 23 23 2) Select the source (Neutron or Photon) and source type (Monochromatic or TOF). 24 24 25 *NOTE! The computational difference between the sources is only the 25 *NOTE! The computational difference between the sources is only the 26 26 gravitational contribution due to the mass of the particles.* 27 27 28 3) Change the default values of the instrumental parameters as required. Be 28 3) Change the default values of the instrumental parameters as required. Be 29 29 careful to note that distances are specified in cm! 30 30 31 4) Enter values for the source wavelength(s), |lambda|\ , and its spread (= FWHM/|lambda|\).32 33 For monochromatic sources, the inputs are just one value. For TOF sources, 34 the minimum and maximum values should be separated by a '-' to specify a 31 4) Enter values for the source wavelength(s), $\lambda$, and its spread (= $\text{FWHM}/\lambda$). 32 33 For monochromatic sources, the inputs are just one value. For TOF sources, 34 the minimum and maximum values should be separated by a '-' to specify a 35 35 range. 36 37 Optionally, the wavelength (BUT NOT of the wavelength spread) can be extended 38 by adding '; nn' where the 'nn' specifies the number of the bins for the 39 numerical integration. The default value is nn = 10. The same number of bins 36 37 Optionally, the wavelength (BUT NOT of the wavelength spread) can be extended 38 by adding '; nn' where the 'nn' specifies the number of the bins for the 39 numerical integration. The default value is nn = 10. The same number of bins 40 40 will be used for the corresponding wavelength spread. 41 41 42 5) For TOF, the default wavelength spectrum is flat. A custom spectral 43 distribution file (2-column text: wavelength (|Ang|\) vs Intensity) can also 42 5) For TOF, the default wavelength spectrum is flat. A custom spectral 43 distribution file (2-column text: wavelength (|Ang|\) vs Intensity) can also 44 44 be loaded by selecting *Add new* in the combo box. 45 45 46 6) When ready, click the *Compute* button. Depending on the computation the 46 6) When ready, click the *Compute* button. Depending on the computation the 47 47 calculation time will vary. 48 48 49 7) 1D and 2D dQ values will be displayed at the bottom of the panel, and a 2D50 resolution weight distribution (a 2D elliptical Gaussian function) will also 51 be displayed in the plot panel even if the Q inputs are outside of the49 7) 1D and 2D $dQ$ values will be displayed at the bottom of the panel, and a 2D 50 resolution weight distribution (a 2D elliptical Gaussian function) will also 51 be displayed in the plot panel even if the $Q$ inputs are outside of the 52 52 detector limit (the red lines indicate the limits of the detector). 53 54 TOF only: green lines indicate the limits of the maximum Q range accessible53 54 TOF only: green lines indicate the limits of the maximum $Q$ range accessible 55 55 for the longest wavelength due to the size of the detector. 56 57 Note that the effect from the beam block/stop is ignored, so in the small Q58 region near the beam block/stop59 56 60 [ie., Q < 2. |pi|\ .(beam block diameter) / (sample-to-detector distance) / |lambda|\_min] 57 Note that the effect from the beam block/stop is ignored, so in the small $Q$ 58 region near the beam block/stop 59 60 [i.e., $Q < (2 \pi \cdot \text{beam block diameter}) / (\text{sample-to-detector distance} \cdot \lambda_\text{min})$] 61 61 62 62 the variance is slightly under estimated. 63 63 64 8) A summary of the calculation is written to the SasView *Console* at the 64 8) A summary of the calculation is written to the SasView *Console* at the 65 65 bottom of the main SasView window. 66 66 67 .. image:: resolution_tutor. gif67 .. image:: resolution_tutor.png 68 68 69 69 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ … … 74 74 The scattering wave transfer vector is by definition 75 75 76 .. image:: q. gif76 .. image:: q.png 77 77 78 In the small-angle limit, the variance of Q is to a first-order78 In the small-angle limit, the variance of $Q$ is to a first-order 79 79 approximation 80 80 81 .. image:: sigma_q. gif81 .. image:: sigma_q.png 82 82 83 83 The geometric and gravitational contributions can then be summarised as 84 84 85 .. image:: sigma_table. gif85 .. image:: sigma_table.png 86 86 87 Finally, a Gaussian function is used to describe the 2D weighting distribution 88 of the uncertainty in Q.87 Finally, a Gaussian function is used to describe the 2D weighting distribution 88 of the uncertainty in $Q$. 89 89 90 90 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ … … 93 93 ---------- 94 94 95 D.F.R. Mildner and J.M. Carpenter 95 D.F.R. Mildner and J.M. Carpenter 96 96 *J. Appl. Cryst.* 17 (1984) 249-256 97 97 98 D.F.R. Mildner, J.M. Carpenter and D.L. Worcester 98 D.F.R. Mildner, J.M. Carpenter and D.L. Worcester 99 99 *J. Appl. Cryst.* 19 (1986) 311-319 100 100 -
src/sas/sasgui/perspectives/calculator/media/sas_calculator_help.rst
rda456fb r5ed76f8 19 19 ------ 20 20 21 In general, a particle with a volume *V* can be described by an ensemble22 containing *N* 3-dimensional rectangular pixels where each pixel is much23 smaller than *V*.21 In general, a particle with a volume $V$ can be described by an ensemble 22 containing $N$ 3-dimensional rectangular pixels where each pixel is much 23 smaller than $V$. 24 24 25 Assuming that all the pixel sizes are the same, the elastic scattering 25 Assuming that all the pixel sizes are the same, the elastic scattering 26 26 intensity from the particle is 27 27 28 .. image:: gen_i. gif28 .. image:: gen_i.png 29 29 30 30 Equation 1. 31 31 32 where |beta|\ :sub:`j` and *r*\ :sub:`j` are the scattering length density and33 the position of the j'thpixel respectively.32 where $\beta_j$ and $r_j$ are the scattering length density and 33 the position of the $j^\text{th}$ pixel respectively. 34 34 35 The total volume *V*35 The total volume $V$ 36 36 37 .. image:: v_j.gif37 .. math:: 38 38 39 for |beta|\ :sub:`j` |noteql|\0 where *v*\ :sub:`j` is the volume of the j'th 40 pixel (or the j'th natural atomic volume (= atomic mass / (natural molar 39 V = \sum_j^N v_j 40 41 for $\beta_j \ne 0$ where $v_j$ is the volume of the $j^\text{th}$ 42 pixel (or the $j^\text{th}$ natural atomic volume (= atomic mass / (natural molar 41 43 density * Avogadro number) for the atomic structures). 42 44 43 *V* can be corrected by users. This correction is useful especially for an 44 atomic structure (such as taken from a PDB file) to get the right normalization. 45 $V$ can be corrected by users. This correction is useful especially for an 46 atomic structure (such as taken from a PDB file) to get the right normalization. 45 47 46 *NOTE! * |beta|\ :sub:`j` *displayed in the GUI may be incorrect but this will not48 *NOTE! $\beta_j$ displayed in the GUI may be incorrect but this will not 47 49 affect the scattering computation if the correction of the total volume V is made.* 48 50 49 The scattering length density (SLD) of each pixel, where the SLD is uniform, is 50 a combination of the nuclear and magnetic SLDs and depends on the spin states 51 The scattering length density (SLD) of each pixel, where the SLD is uniform, is 52 a combination of the nuclear and magnetic SLDs and depends on the spin states 51 53 of the neutrons as follows. 52 54 … … 54 56 ^^^^^^^^^^^^^^^^^^^ 55 57 56 For magnetic scattering, only the magnetization component, *M*\ :sub:`perp`\ ,57 perpendicular to the scattering vector *Q* contributes to the magnetic58 For magnetic scattering, only the magnetization component, $M_\perp$, 59 perpendicular to the scattering vector $Q$ contributes to the magnetic 58 60 scattering length. 59 61 60 .. image:: mag_vector. bmp62 .. image:: mag_vector.png 61 63 62 64 The magnetic scattering length density is then 63 65 64 .. image:: dm_eq. gif66 .. image:: dm_eq.png 65 67 66 where the gyromagnetic ratio |gamma| = -1.913, |mu|\ :sub:`B` is the Bohr67 magneton, *r*\ :sub:`0` is the classical radius of electron, and |sigma| is the68 where the gyromagnetic ratio is $\gamma = -1.913$, $\mu_B$ is the Bohr 69 magneton, $r_0$ is the classical radius of electron, and $\sigma$ is the 68 70 Pauli spin. 69 71 70 72 For a polarized neutron, the magnetic scattering is depending on the spin states. 71 73 72 Let us consider that the incident neutrons are polarised both parallel (+) and 73 anti-parallel (-) to the x' axis (see below). The possible states after 74 scattering from the sample are then 74 Let us consider that the incident neutrons are polarised both parallel (+) and 75 anti-parallel (-) to the x' axis (see below). The possible states after 76 scattering from the sample are then 75 77 76 78 * Non-spin flips: (+ +) and (- -) 77 79 * Spin flips: (+ -) and (- +) 78 80 79 .. image:: gen_mag_pic. bmp81 .. image:: gen_mag_pic.png 80 82 81 Now let us assume that the angles of the *Q* vector and the spin-axis (x') 82 to the x-axis are |phi| and |theta|\ :sub:`up` respectively (see above). Then,83 depending upon the polarization (spin) state of neutrons, the scattering 84 length densities, including the nuclear scattering length density ( |beta|\ :sub:`N`\ )83 Now let us assume that the angles of the *Q* vector and the spin-axis (x') 84 to the x-axis are $\phi$ and $\theta_\text{up}$ respectively (see above). Then, 85 depending upon the polarization (spin) state of neutrons, the scattering 86 length densities, including the nuclear scattering length density ($\beta_N$) 85 87 are given as 86 88 87 89 * for non-spin-flips 88 90 89 .. image:: sld1. gif91 .. image:: sld1.png 90 92 91 93 * for spin-flips 92 94 93 .. image:: sld2. gif95 .. image:: sld2.png 94 96 95 97 where 96 98 97 .. image:: mxp. gif99 .. image:: mxp.png 98 100 99 .. image:: myp. gif101 .. image:: myp.png 100 102 101 .. image:: mzp. gif103 .. image:: mzp.png 102 104 103 .. image:: mqx. gif105 .. image:: mqx.png 104 106 105 .. image:: mqy. gif107 .. image:: mqy.png 106 108 107 Here the *M0*\ :sub:`x`\ , *M0*\ :sub:`y` and *M0*\ :sub:`z` are the x, y and z108 components of the magnetisation vector in the laboratory xyz frame.109 Here the $M0_x$, $M0_y$ and $M0_z$ are the $x$, $y$ and $z$ 110 components of the magnetisation vector in the laboratory $xyz$ frame. 109 111 110 112 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ … … 113 115 -------------- 114 116 115 .. image:: gen_gui_help. bmp117 .. image:: gen_gui_help.png 116 118 117 After computation the result will appear in the *Theory* box in the SasView 119 After computation the result will appear in the *Theory* box in the SasView 118 120 *Data Explorer* panel. 119 121 120 *Up_frac_in* and *Up_frac_out* are the ratio 122 *Up_frac_in* and *Up_frac_out* are the ratio 121 123 122 124 (spin up) / (spin up + spin down) 123 125 124 126 of neutrons before the sample and at the analyzer, respectively. 125 127 126 *NOTE 1. The values of* Up_frac_in *and* Up_frac_out *must be in the range 128 *NOTE 1. The values of* Up_frac_in *and* Up_frac_out *must be in the range 127 129 0.0 to 1.0. Both values are 0.5 for unpolarized neutrons.* 128 130 129 *NOTE 2. This computation is totally based on the pixel (or atomic) data fixed 131 *NOTE 2. This computation is totally based on the pixel (or atomic) data fixed 130 132 in xyz coordinates. No angular orientational averaging is considered.* 131 133 132 *NOTE 3. For the nuclear scattering length density, only the real component 134 *NOTE 3. For the nuclear scattering length density, only the real component 133 135 is taken account.* 134 136 … … 139 141 140 142 The SANS Calculator tool can read some PDB, OMF or SLD files but ignores 141 polarized/magnetic scattering when doing so, thus related parameters such as 143 polarized/magnetic scattering when doing so, thus related parameters such as 142 144 *Up_frac_in*, etc, will be ignored. 143 145 144 The calculation for fixed orientation uses Equation 1 above resulting in a 2D 145 output, whereas the scattering calculation averaged over all the orientations 146 The calculation for fixed orientation uses Equation 1 above resulting in a 2D 147 output, whereas the scattering calculation averaged over all the orientations 146 148 uses the Debye equation below providing a 1D output 147 149 148 .. image:: gen_debye_eq. gif150 .. image:: gen_debye_eq.png 149 151 150 where *v*\ :sub:`j` |beta|\ :sub:`j` |equiv| *b*\ :sub:`j` is the scattering151 length of the j'th atom. The calculation output is passed to the *Data Explorer*152 where $v_j \beta_j \equiv b_j$ is the scattering 153 length of the $j^\text{th}$ atom. The calculation output is passed to the *Data Explorer* 152 154 for further use. 153 155 -
src/sas/sasgui/perspectives/calculator/media/sld_calculator_help.rst
rf93b473f r5ed76f8 10 10 ----------- 11 11 12 The neutron scattering length density (SLD ) is defined as12 The neutron scattering length density (SLD, $\beta_N$) is defined as 13 13 14 SLD = (b_c1 + b_c2 + ... + b_cn) / Vm 14 .. math:: 15 15 16 where b_ci is the bound coherent scattering length of ith of n atoms in a molecule 17 with the molecular volume Vm 16 \beta_N = (b_{c1} + b_{c2} + ... + b_{cn}) / V_m 17 18 where $b_{ci}$ is the bound coherent scattering length of ith of n atoms in a molecule 19 with the molecular volume $V_m$. 18 20 19 21 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ … … 22 24 ---------------------------- 23 25 24 To calculate scattering length densities enter the empirical formula of a 26 To calculate scattering length densities enter the empirical formula of a 25 27 compound and its mass density and click "Calculate". 26 28 27 Entering a wavelength value is optional (a default value of 6.0 |Ang| will 29 Entering a wavelength value is optional (a default value of 6.0 |Ang| will 28 30 be used). 29 31 … … 38 40 * Parentheses can be nested, such as "(CaCO3(H2O)6)1". 39 41 40 * Isotopes are represented by their atomic number in *square brackets*, such 42 * Isotopes are represented by their atomic number in *square brackets*, such 41 43 as "CaCO[18]3+6H2O", H[1], or H[2]. 42 44 43 45 * Numbers of atoms can be integer or decimal, such as "CaCO3+(3HO0.5)2". 44 46 45 * The SLD of mixtures can be calculated as well. For example, for a 70-30 47 * The SLD of mixtures can be calculated as well. For example, for a 70-30 46 48 mixture of H2O/D2O write "H14O7+D6O3" or more simply "H7D3O5" (i.e. this says 47 49 7 hydrogens, 3 deuteriums, and 5 oxygens) and enter a mass density calculated 48 50 on the percentages of H2O and D2O. 49 51 50 * Type "C[13]6 H[2]12 O[18]6" for C(13)6H(2)12O(18)6 (6 Carbon-13 atoms, 12 52 * Type "C[13]6 H[2]12 O[18]6" for C(13)6H(2)12O(18)6 (6 Carbon-13 atoms, 12 51 53 deuterium atoms, and 6 Oxygen-18 atoms). 52 54 53 55 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 54 56 55 .. note:: This help document was last changed by Steve King, 01May201557 .. note:: This help document was last changed by Paul Kienzle, 05Apr2017 56 58 -
src/sas/sasgui/perspectives/calculator/media/slit_calculator_help.rst
rf93b473f r5ed76f8 11 11 ----------- 12 12 13 This tool enables X-ray users to calculate the slit size (FWHM/2) for smearing 13 This tool enables X-ray users to calculate the slit size (FWHM/2) for smearing 14 14 based on their half beam profile data. 15 15 16 16 *NOTE! Whilst it may have some more generic applicability, the calculator has 17 only been tested with beam profile data from Anton-Paar SAXSess*\ |TM|\ 18 *software.* 17 only been tested with beam profile data from Anton-Paar SAXSess:sup:`TM` software.* 19 18 20 19 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ … … 27 26 2) Load a beam profile file in the *Data* field using the *Browse* button. 28 27 29 *NOTE! To see an example of the beam profile file format, visit the file 28 *NOTE! To see an example of the beam profile file format, visit the file 30 29 beam profile.DAT in your {installation_directory}/SasView/test folder.* 31 30 32 3) Once a data is loaded, the slit size is automatically computed and displayed 31 3) Once a data is loaded, the slit size is automatically computed and displayed 33 32 in the tool window. 34 33 35 *NOTE! The beam profile file does not carry any information about the units of 34 *NOTE! The beam profile file does not carry any information about the units of 36 35 the Q data. This calculator assumes the data has units of 1/\ |Ang|\ . If the 37 36 data is not in these units it must be manually converted beforehand.* -
src/sas/sasgui/perspectives/calculator/model_editor.py
ra1b8fee r69363c7 31 31 import re 32 32 import logging 33 import datetime 34 33 35 from wx.py.editwindow import EditWindow 36 34 37 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 38 35 39 from .pyconsole import show_model_output, check_model 36 40 37 41 logger = logging.getLogger(__name__) 38 39 42 40 43 if sys.platform.count("win32") > 0: … … 78 81 a Modal Dialog. 79 82 80 :TODO the buil din compiler currently balks at when it tries to import83 :TODO the built in compiler currently balks at when it tries to import 81 84 a model whose name contains spaces or symbols (such as + ... underscore 82 85 should be fine). Have fixed so the editor cannot save such a file name … … 106 109 self.model2_string = "cylinder" 107 110 self.name = 'Sum' + M_NAME 108 self.factor = 'scale_factor'109 111 self._notes = '' 110 112 self._operator = '+' … … 133 135 self.model2_name = str(self.model2.GetValue()) 134 136 self.good_name = True 135 self.fill_op rator_combox()137 self.fill_operator_combox() 136 138 137 139 def _layout_name(self): … … 336 338 list_fnames = os.listdir(self.plugin_dir) 337 339 # fake existing regular model name list 338 m_list = [model + ".py" for model in self.model_list]340 m_list = [model.name + ".py" for model in self.model_list] 339 341 list_fnames.append(m_list) 340 342 if t_fname in list_fnames and title != mname: … … 491 493 a sum or multiply model then create the appropriate string 492 494 """ 493 494 495 name = '' 495 496 496 if operator == '*': 497 497 name = 'Multi' 498 factor = 'BackGround' 499 f_oper = '+' 498 factor = 'background' 500 499 else: 501 500 name = 'Sum' 502 501 factor = 'scale_factor' 503 f_oper = '*' 504 505 self.factor = factor 502 506 503 self._operator = operator 507 self.explanation = " Plugin Model = %s %s (model1 %s model2)\n" % \508 (self.factor, f_oper, self._operator)504 self.explanation = (" Plugin_model = scale_factor * (model_1 {} " 505 "model_2) + background").format(operator) 509 506 self.explanationctr.SetLabel(self.explanation) 510 507 self.name = name + M_NAME 511 508 512 509 513 def fill_op rator_combox(self):510 def fill_operator_combox(self): 514 511 """ 515 512 fill the current combobox with the operator … … 527 524 return [self.model1_name, self.model2_name] 528 525 529 def write_string(self, fname, name1, name2):526 def write_string(self, fname, model1_name, model2_name): 530 527 """ 531 528 Write and Save file … … 533 530 self.fname = fname 534 531 description = self.desc_tcl.GetValue().lstrip().rstrip() 535 if description == '': 536 description = name1 + self._operator + name2 537 text = self._operator_choice.GetValue() 538 if text.count('+') > 0: 539 factor = 'scale_factor' 540 f_oper = '*' 541 default_val = '1.0' 542 else: 543 factor = 'BackGround' 544 f_oper = '+' 545 default_val = '0.0' 546 path = self.fname 547 try: 548 out_f = open(path, 'w') 549 except: 550 raise 551 lines = SUM_TEMPLATE.split('\n') 552 for line in lines: 553 try: 554 if line.count("scale_factor"): 555 line = line.replace('scale_factor', factor) 556 #print "scale_factor", line 557 if line.count("= %s"): 558 out_f.write(line % (default_val) + "\n") 559 elif line.count("import Model as P1"): 560 if self.is_p1_custom: 561 line = line.replace('#', '') 562 out_f.write(line % name1 + "\n") 563 else: 564 out_f.write(line + "\n") 565 elif line.count("import %s as P1"): 566 if not self.is_p1_custom: 567 line = line.replace('#', '') 568 out_f.write(line % (name1) + "\n") 569 else: 570 out_f.write(line + "\n") 571 elif line.count("import Model as P2"): 572 if self.is_p2_custom: 573 line = line.replace('#', '') 574 out_f.write(line % name2 + "\n") 575 else: 576 out_f.write(line + "\n") 577 elif line.count("import %s as P2"): 578 if not self.is_p2_custom: 579 line = line.replace('#', '') 580 out_f.write(line % (name2) + "\n") 581 else: 582 out_f.write(line + "\n") 583 elif line.count("P1 = find_model"): 584 out_f.write(line % (name1) + "\n") 585 elif line.count("P2 = find_model"): 586 out_f.write(line % (name2) + "\n") 587 588 elif line.count("self.description = '%s'"): 589 out_f.write(line % description + "\n") 590 #elif line.count("run") and line.count("%s"): 591 # out_f.write(line % self._operator + "\n") 592 #elif line.count("evalDistribution") and line.count("%s"): 593 # out_f.write(line % self._operator + "\n") 594 elif line.count("return") and line.count("%s") == 2: 595 #print "line return", line 596 out_f.write(line % (f_oper, self._operator) + "\n") 597 elif line.count("out2")and line.count("%s"): 598 out_f.write(line % self._operator + "\n") 599 else: 600 out_f.write(line + "\n") 601 except: 602 raise 603 out_f.close() 604 #else: 605 # msg = "Name exists already." 532 desc_line = '' 533 if description.strip() != '': 534 # Sasmodels generates a description for us. If the user provides 535 # their own description, add a line to overwrite the sasmodels one 536 desc_line = "\nmodel_info.description = '{}'".format(description) 537 name = os.path.splitext(os.path.basename(self.fname))[0] 538 output = SUM_TEMPLATE.format(name=name, model1=model1_name, 539 model2=model2_name, operator=self._operator, desc_line=desc_line) 540 with open(self.fname, 'w') as out_f: 541 out_f.write(output) 606 542 607 543 def compile_file(self, path): … … 643 579 self.name_hsizer = None 644 580 self.name_tcl = None 581 self.overwrite_cb = None 645 582 self.desc_sizer = None 646 583 self.desc_tcl = None … … 657 594 self.warning = "" 658 595 #This does not seem to be used anywhere so commenting out for now 659 # -- PDB 2/26/17 596 # -- PDB 2/26/17 660 597 #self._description = "New Plugin Model" 661 598 self.function_tcl = None … … 689 626 #title name [string] 690 627 name_txt = wx.StaticText(self, -1, 'Function Name : ') 691 overwrite_cb = wx.CheckBox(self, -1, "Overwrite existing plugin model of this name?", (10, 10))692 overwrite_cb.SetValue(False)693 overwrite_cb.SetToolTipString("Overwrite it if already exists?")694 wx.EVT_CHECKBOX(self, overwrite_cb.GetId(), self.on_over_cb)628 self.overwrite_cb = wx.CheckBox(self, -1, "Overwrite existing plugin model of this name?", (10, 10)) 629 self.overwrite_cb.SetValue(False) 630 self.overwrite_cb.SetToolTipString("Overwrite it if already exists?") 631 wx.EVT_CHECKBOX(self, self.overwrite_cb.GetId(), self.on_over_cb) 695 632 self.name_tcl = wx.TextCtrl(self, -1, size=(PANEL_WIDTH * 3 / 5, -1)) 696 633 self.name_tcl.Bind(wx.EVT_TEXT_ENTER, self.on_change_name) … … 700 637 self.name_tcl.SetToolTipString(hint_name) 701 638 self.name_hsizer.AddMany([(self.name_tcl, 0, wx.LEFT | wx.TOP, 0), 702 ( overwrite_cb, 0, wx.LEFT, 20)])639 (self.overwrite_cb, 0, wx.LEFT, 20)]) 703 640 self.name_sizer.AddMany([(name_txt, 0, wx.LEFT | wx.TOP, 10), 704 641 (self.name_hsizer, 0, … … 740 677 self.param_sizer.AddMany([(param_txt, 0, wx.LEFT, 10), 741 678 (self.param_tcl, 1, wx.EXPAND | wx.ALL, 10)]) 742 679 743 680 # Parameters with polydispersity 744 681 pd_param_txt = wx.StaticText(self, -1, 'Fit Parameters requiring ' + \ … … 755 692 self.pd_param_tcl.setDisplayLineNumbers(True) 756 693 self.pd_param_tcl.SetToolTipString(pd_param_tip) 757 694 758 695 self.param_sizer.AddMany([(pd_param_txt, 0, wx.LEFT, 10), 759 696 (self.pd_param_tcl, 1, wx.EXPAND | wx.ALL, 10)]) … … 855 792 exec "float(math.%s)" % item 856 793 self.math_combo.Append(str(item)) 857 except :794 except Exception: 858 795 self.math_combo.Append(str(item) + "()") 859 796 self.math_combo.Bind(wx.EVT_COMBOBOX, self._on_math_select) … … 980 917 msg = "Name exists already." 981 918 982 # Prepare the messagebox919 # 983 920 if self.base is not None and not msg: 984 921 self.base.update_custom_combo() 985 # Passed exception in import test as it will fail for sasmodels.sasview_model class986 # Should add similar test for new style?987 Model = None988 try:989 exec "from %s import Model" % name990 except:991 logger.error(sys.exc_value)992 922 993 923 # Prepare the messagebox … … 995 925 info = 'Error' 996 926 color = 'red' 927 self.overwrite_cb.SetValue(True) 928 self.overwrite_name = True 997 929 else: 998 930 self._notes = result … … 1020 952 :param func_str: content of func; Strings 1021 953 """ 1022 try: 1023 out_f = open(fname, 'w') 1024 except: 1025 raise 1026 # Prepare the content of the function 1027 lines = CUSTOM_TEMPLATE.split('\n') 1028 1029 has_scipy = func_str.count("scipy.") 1030 if has_scipy: 1031 lines.insert(0, 'import scipy') 1032 1033 # Think about 2D later 1034 #self.is_2d = func_str.count("#self.ndim = 2") 1035 #line_2d = '' 1036 #if self.is_2d: 1037 # line_2d = CUSTOM_2D_TEMP.split('\n') 1038 1039 # Also think about test later 1040 #line_test = TEST_TEMPLATE.split('\n') 1041 #local_params = '' 1042 #spaces = ' '#8spaces 1043 spaces4 = ' '*4 1044 spaces13 = ' '*13 1045 spaces16 = ' '*16 954 out_f = open(fname, 'w') 955 956 out_f.write(CUSTOM_TEMPLATE % { 957 'name': name, 958 'title': 'User model for ' + name, 959 'description': desc_str, 960 'date': datetime.datetime.now().strftime('%YYYY-%mm-%dd'), 961 }) 962 963 # Write out parameters 1046 964 param_names = [] # to store parameter names 1047 has_scipy = func_str.count("scipy.") 1048 if has_scipy: 1049 lines.insert(0, 'import scipy') 1050 1051 # write function here 1052 for line in lines: 1053 # The location where to put the strings is 1054 # hard-coded in the template as shown below. 1055 out_f.write(line + '\n') 1056 if line.count('#name'): 1057 out_f.write('name = "%s" \n' % name) 1058 elif line.count('#title'): 1059 out_f.write('title = "User model for %s"\n' % name) 1060 elif line.count('#description'): 1061 out_f.write('description = "%s"\n' % desc_str) 1062 elif line.count('#parameters'): 1063 out_f.write('parameters = [ \n') 1064 for param_line in param_str.split('\n'): 1065 p_line = param_line.lstrip().rstrip() 1066 if p_line: 1067 pname, pvalue = self.get_param_helper(p_line) 1068 param_names.append(pname) 1069 out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', ''],\n" % (spaces16, pname, pvalue)) 1070 for param_line in pd_param_str.split('\n'): 1071 p_line = param_line.lstrip().rstrip() 1072 if p_line: 1073 pname, pvalue = self.get_param_helper(p_line) 1074 param_names.append(pname) 1075 out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', ''],\n" % (spaces16, pname, pvalue)) 1076 out_f.write('%s]\n' % spaces13) 1077 1078 # No form_volume or ER available in simple model editor 1079 out_f.write('def form_volume(*arg): \n') 1080 out_f.write(' return 1.0 \n') 1081 out_f.write('\n') 1082 out_f.write('def ER(*arg): \n') 1083 out_f.write(' return 1.0 \n') 1084 1085 # function to compute 1086 out_f.write('\n') 1087 out_f.write('def Iq(x ') 1088 for name in param_names: 1089 out_f.write(', %s' % name) 1090 out_f.write('):\n') 965 pd_params = [] 966 out_f.write('parameters = [ \n') 967 out_f.write('# ["name", "units", default, [lower, upper], "type", "description"],\n') 968 for pname, pvalue, desc in self.get_param_helper(param_str): 969 param_names.append(pname) 970 out_f.write(" ['%s', '', %s, [-inf, inf], '', '%s'],\n" 971 % (pname, pvalue, desc)) 972 for pname, pvalue, desc in self.get_param_helper(pd_param_str): 973 param_names.append(pname) 974 pd_params.append(pname) 975 out_f.write(" ['%s', '', %s, [-inf, inf], 'volume', '%s'],\n" 976 % (pname, pvalue, desc)) 977 out_f.write(' ]\n') 978 979 # Write out function definition 980 out_f.write('def Iq(%s):\n' % ', '.join(['x'] + param_names)) 981 out_f.write(' """Absolute scattering"""\n') 982 if "scipy." in func_str: 983 out_f.write(' import scipy') 984 if "numpy." in func_str: 985 out_f.write(' import numpy') 986 if "np." in func_str: 987 out_f.write(' import numpy as np') 1091 988 for func_line in func_str.split('\n'): 1092 989 out_f.write('%s%s\n' % (spaces4, func_line)) 1093 1094 Iqxy_string = 'return Iq(numpy.sqrt(x**2+y**2) ' 1095 990 out_f.write('## uncomment the following if Iq works for vector x\n') 991 out_f.write('#Iq.vectorized = True\n') 992 993 # If polydisperse, create place holders for form_volume, ER and VR 994 if pd_params: 995 out_f.write('\n') 996 out_f.write(CUSTOM_TEMPLATE_PD % {'args': ', '.join(pd_params)}) 997 998 # Create place holder for Iqxy 1096 999 out_f.write('\n') 1097 out_f.write('def Iqxy(x, y ') 1098 for name in param_names: 1099 out_f.write(', %s' % name) 1100 Iqxy_string += ', ' + name 1101 out_f.write('):\n') 1102 Iqxy_string += ')' 1103 out_f.write('%s%s\n' % (spaces4, Iqxy_string)) 1000 out_f.write('#def Iqxy(%s):\n' % ', '.join(["x", "y"] + param_names)) 1001 out_f.write('# """Absolute scattering of oriented particles."""\n') 1002 out_f.write('# ...\n') 1003 out_f.write('# return oriented_form(x, y, args)\n') 1004 out_f.write('## uncomment the following if Iqxy works for vector x, y\n') 1005 out_f.write('#Iqxy.vectorized = True\n') 1104 1006 1105 1007 out_f.close() 1106 1008 1107 def get_param_helper(self, line): 1108 """ 1109 Get string in line to define the params dictionary 1110 1111 :param line: one line of string got from the param_str 1112 """ 1113 items = line.split(";") 1114 for item in items: 1115 name = item.split("=")[0].lstrip().rstrip() 1116 try: 1117 value = item.split("=")[1].lstrip().rstrip() 1118 float(value) 1119 except: 1120 value = 1.0 # default 1121 1122 return name, value 1009 def get_param_helper(self, param_str): 1010 """ 1011 yield a sequence of name, value pairs for the parameters in param_str 1012 1013 Parameters can be defined by one per line by name=value, or multiple 1014 on the same line by separating the pairs by semicolon or comma. The 1015 value is optional and defaults to "1.0". 1016 """ 1017 for line in param_str.replace(';', ',').split('\n'): 1018 for item in line.split(','): 1019 defn, desc = item.split('#', 1) if '#' in item else (item, '') 1020 name, value = defn.split('=', 1) if '=' in defn else (defn, '1.0') 1021 if name: 1022 yield [v.strip() for v in (name, value, desc)] 1123 1023 1124 1024 def set_function_helper(self, line): … … 1154 1054 running "file:///...." 1155 1055 1156 :param evt: Triggers on clicking the help button1157 """1056 :param evt: Triggers on clicking the help button 1057 """ 1158 1058 1159 1059 _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" … … 1198 1098 ## Templates for plugin models 1199 1099 1200 CUSTOM_TEMPLATE = """ 1100 CUSTOM_TEMPLATE = '''\ 1101 r""" 1102 Definition 1103 ---------- 1104 1105 Calculates %(name)s. 1106 1107 %(description)s 1108 1109 References 1110 ---------- 1111 1112 Authorship and Verification 1113 --------------------------- 1114 1115 * **Author:** --- **Date:** %(date)s 1116 * **Last Modified by:** --- **Date:** %(date)s 1117 * **Last Reviewed by:** --- **Date:** %(date)s 1118 """ 1119 1201 1120 from math import * 1202 import os 1203 import sys 1204 import numpy 1205 1206 #name 1207 1208 #title 1209 1210 #description 1211 1212 #parameters 1213 1121 from numpy import inf 1122 1123 name = "%(name)s" 1124 title = "%(title)s" 1125 description = """%(description)s""" 1126 1127 ''' 1128 1129 CUSTOM_TEMPLATE_PD = '''\ 1130 def form_volume(%(args)s): 1131 """ 1132 Volume of the particles used to compute absolute scattering intensity 1133 and to weight polydisperse parameter contributions. 1134 """ 1135 return 0.0 1136 1137 def ER(%(args)s): 1138 """ 1139 Effective radius of particles to be used when computing structure factors. 1140 1141 Input parameters are vectors ranging over the mesh of polydispersity values. 1142 """ 1143 return 0.0 1144 1145 def VR(%(args)s): 1146 """ 1147 Volume ratio of particles to be used when computing structure factors. 1148 1149 Input parameters are vectors ranging over the mesh of polydispersity values. 1150 """ 1151 return 1.0 1152 ''' 1153 1154 SUM_TEMPLATE = """ 1155 from sasmodels.core import load_model_info 1156 from sasmodels.sasview_model import make_model_from_info 1157 1158 model_info = load_model_info('{model1}{operator}{model2}') 1159 model_info.name = '{name}'{desc_line} 1160 Model = make_model_from_info(model_info) 1214 1161 """ 1215 1216 CUSTOM_2D_TEMP = """1217 def run(self, x=0.0, y=0.0):1218 if x.__class__.__name__ == 'list':1219 x_val = x[0]1220 y_val = y[0]*0.01221 return self.function(x_val, y_val)1222 elif x.__class__.__name__ == 'tuple':1223 msg = "Tuples are not allowed as input to BaseComponent models"1224 raise ValueError, msg1225 else:1226 return self.function(x, 0.0)1227 def runXY(self, x=0.0, y=0.0):1228 if x.__class__.__name__ == 'list':1229 return self.function(x, y)1230 elif x.__class__.__name__ == 'tuple':1231 msg = "Tuples are not allowed as input to BaseComponent models"1232 raise ValueError, msg1233 else:1234 return self.function(x, y)1235 def evalDistribution(self, qdist):1236 if qdist.__class__.__name__ == 'list':1237 msg = "evalDistribution expects a list of 2 ndarrays"1238 if len(qdist)!=2:1239 raise RuntimeError, msg1240 if qdist[0].__class__.__name__ != 'ndarray':1241 raise RuntimeError, msg1242 if qdist[1].__class__.__name__ != 'ndarray':1243 raise RuntimeError, msg1244 v_model = numpy.vectorize(self.runXY, otypes=[float])1245 iq_array = v_model(qdist[0], qdist[1])1246 return iq_array1247 elif qdist.__class__.__name__ == 'ndarray':1248 v_model = numpy.vectorize(self.runXY, otypes=[float])1249 iq_array = v_model(qdist)1250 return iq_array1251 """1252 TEST_TEMPLATE = """1253 ######################################################################1254 ## THIS IS FOR TEST. DO NOT MODIFY THE FOLLOWING LINES!!!!!!!!!!!!!!!!1255 1162 if __name__ == "__main__": 1256 m= Model()1257 out1 = m.runXY(0.0)1258 out2 = m.runXY(0.01)1259 isfine1 = numpy.isfinite(out1)1260 isfine2 = numpy.isfinite(out2)1261 print "Testing the value at Q = 0.0:"1262 print out1, " : finite? ", isfine11263 print "Testing the value at Q = 0.01:"1264 print out2, " : finite? ", isfine21265 if isfine1 and isfine2:1266 print "===> Simple Test: Passed!"1267 else:1268 print "===> Simple Test: Failed!"1269 """1270 SUM_TEMPLATE = """1271 # A sample of an experimental model function for Sum/Multiply(Pmodel1,Pmodel2)1272 import os1273 import sys1274 import copy1275 import collections1276 1277 import numpy1278 1279 from sas.sascalc.fit.pluginmodel import Model1DPlugin1280 from sasmodels.sasview_model import find_model1281 1282 class Model(Model1DPlugin):1283 name = os.path.splitext(os.path.basename(__file__))[0]1284 is_multiplicity_model = False1285 def __init__(self, multiplicity=1):1286 Model1DPlugin.__init__(self, name='')1287 P1 = find_model('%s')1288 P2 = find_model('%s')1289 p_model1 = P1()1290 p_model2 = P2()1291 ## Setting model name model description1292 self.description = '%s'1293 if self.name.rstrip().lstrip() == '':1294 self.name = self._get_name(p_model1.name, p_model2.name)1295 if self.description.rstrip().lstrip() == '':1296 self.description = p_model1.name1297 self.description += p_model2.name1298 self.fill_description(p_model1, p_model2)1299 1300 ## Define parameters1301 self.params = collections.OrderedDict()1302 1303 ## Parameter details [units, min, max]1304 self.details = {}1305 ## Magnetic Panrameters1306 self.magnetic_params = []1307 # non-fittable parameters1308 self.non_fittable = p_model1.non_fittable1309 self.non_fittable += p_model2.non_fittable1310 1311 ##models1312 self.p_model1= p_model11313 self.p_model2= p_model21314 1315 1316 ## dispersion1317 self._set_dispersion()1318 ## Define parameters1319 self._set_params()1320 ## New parameter:scaling_factor1321 self.params['scale_factor'] = %s1322 1323 ## Parameter details [units, min, max]1324 self._set_details()1325 self.details['scale_factor'] = ['', 0.0, numpy.inf]1326 1327 1328 #list of parameter that can be fitted1329 self._set_fixed_params()1330 1331 ## parameters with orientation1332 self.orientation_params = []1333 for item in self.p_model1.orientation_params:1334 new_item = "p1_" + item1335 if not new_item in self.orientation_params:1336 self.orientation_params.append(new_item)1337 1338 for item in self.p_model2.orientation_params:1339 new_item = "p2_" + item1340 if not new_item in self.orientation_params:1341 self.orientation_params.append(new_item)1342 ## magnetic params1343 self.magnetic_params = []1344 for item in self.p_model1.magnetic_params:1345 new_item = "p1_" + item1346 if not new_item in self.magnetic_params:1347 self.magnetic_params.append(new_item)1348 1349 for item in self.p_model2.magnetic_params:1350 new_item = "p2_" + item1351 if not new_item in self.magnetic_params:1352 self.magnetic_params.append(new_item)1353 # get multiplicity if model provide it, else 1.1354 try:1355 multiplicity1 = p_model1.multiplicity1356 try:1357 multiplicity2 = p_model2.multiplicity1358 except:1359 multiplicity2 = 11360 except:1361 multiplicity1 = 11362 multiplicity2 = 11363 ## functional multiplicity of the model1364 self.multiplicity1 = multiplicity11365 self.multiplicity2 = multiplicity21366 self.multiplicity_info = []1367 1368 def _clone(self, obj):1369 import copy1370 obj.params = copy.deepcopy(self.params)1371 obj.description = copy.deepcopy(self.description)1372 obj.details = copy.deepcopy(self.details)1373 obj.dispersion = copy.deepcopy(self.dispersion)1374 obj.p_model1 = self.p_model1.clone()1375 obj.p_model2 = self.p_model2.clone()1376 #obj = copy.deepcopy(self)1377 return obj1378 1379 def _get_name(self, name1, name2):1380 p1_name = self._get_upper_name(name1)1381 if not p1_name:1382 p1_name = name11383 name = p1_name1384 name += "_and_"1385 p2_name = self._get_upper_name(name2)1386 if not p2_name:1387 p2_name = name21388 name += p2_name1389 return name1390 1391 def _get_upper_name(self, name=None):1392 if name is None:1393 return ""1394 upper_name = ""1395 str_name = str(name)1396 for index in range(len(str_name)):1397 if str_name[index].isupper():1398 upper_name += str_name[index]1399 return upper_name1400 1401 def _set_dispersion(self):1402 self.dispersion = collections.OrderedDict()1403 ##set dispersion only from p_model1404 for name , value in self.p_model1.dispersion.iteritems():1405 #if name.lower() not in self.p_model1.orientation_params:1406 new_name = "p1_" + name1407 self.dispersion[new_name]= value1408 for name , value in self.p_model2.dispersion.iteritems():1409 #if name.lower() not in self.p_model2.orientation_params:1410 new_name = "p2_" + name1411 self.dispersion[new_name]= value1412 1413 def function(self, x=0.0):1414 return 01415 1416 def getProfile(self):1417 try:1418 x,y = self.p_model1.getProfile()1419 except:1420 x = None1421 y = None1422 1423 return x, y1424 1425 def _set_params(self):1426 for name , value in self.p_model1.params.iteritems():1427 # No 2D-supported1428 #if name not in self.p_model1.orientation_params:1429 new_name = "p1_" + name1430 self.params[new_name]= value1431 1432 for name , value in self.p_model2.params.iteritems():1433 # No 2D-supported1434 #if name not in self.p_model2.orientation_params:1435 new_name = "p2_" + name1436 self.params[new_name]= value1437 1438 # Set "scale" as initializing1439 self._set_scale_factor()1440 1441 1442 def _set_details(self):1443 for name ,detail in self.p_model1.details.iteritems():1444 new_name = "p1_" + name1445 #if new_name not in self.orientation_params:1446 self.details[new_name]= detail1447 1448 for name ,detail in self.p_model2.details.iteritems():1449 new_name = "p2_" + name1450 #if new_name not in self.orientation_params:1451 self.details[new_name]= detail1452 1453 def _set_scale_factor(self):1454 pass1455 1456 1457 def setParam(self, name, value):1458 # set param to this (p1, p2) model1459 self._setParamHelper(name, value)1460 1461 ## setParam to p model1462 model_pre = ''1463 new_name = ''1464 name_split = name.split('_', 1)1465 if len(name_split) == 2:1466 model_pre = name.split('_', 1)[0]1467 new_name = name.split('_', 1)[1]1468 if model_pre == "p1":1469 if new_name in self.p_model1.getParamList():1470 self.p_model1.setParam(new_name, value)1471 elif model_pre == "p2":1472 if new_name in self.p_model2.getParamList():1473 self.p_model2.setParam(new_name, value)1474 elif name == 'scale_factor':1475 self.params['scale_factor'] = value1476 else:1477 raise ValueError, "Model does not contain parameter %s" % name1478 1479 def getParam(self, name):1480 # Look for dispersion parameters1481 toks = name.split('.')1482 if len(toks)==2:1483 for item in self.dispersion.keys():1484 # 2D not supported1485 if item.lower()==toks[0].lower():1486 for par in self.dispersion[item]:1487 if par.lower() == toks[1].lower():1488 return self.dispersion[item][par]1489 else:1490 # Look for standard parameter1491 for item in self.params.keys():1492 if item.lower()==name.lower():1493 return self.params[item]1494 return1495 #raise ValueError, "Model does not contain parameter %s" % name1496 1497 def _setParamHelper(self, name, value):1498 # Look for dispersion parameters1499 toks = name.split('.')1500 if len(toks)== 2:1501 for item in self.dispersion.keys():1502 if item.lower()== toks[0].lower():1503 for par in self.dispersion[item]:1504 if par.lower() == toks[1].lower():1505 self.dispersion[item][par] = value1506 return1507 else:1508 # Look for standard parameter1509 for item in self.params.keys():1510 if item.lower()== name.lower():1511 self.params[item] = value1512 return1513 1514 raise ValueError, "Model does not contain parameter %s" % name1515 1516 1517 def _set_fixed_params(self):1518 self.fixed = []1519 for item in self.p_model1.fixed:1520 new_item = "p1" + item1521 self.fixed.append(new_item)1522 for item in self.p_model2.fixed:1523 new_item = "p2" + item1524 self.fixed.append(new_item)1525 1526 self.fixed.sort()1527 1528 1529 def run(self, x = 0.0):1530 self._set_scale_factor()1531 return self.params['scale_factor'] %s \1532 (self.p_model1.run(x) %s self.p_model2.run(x))1533 1534 def runXY(self, x = 0.0):1535 self._set_scale_factor()1536 return self.params['scale_factor'] %s \1537 (self.p_model1.runXY(x) %s self.p_model2.runXY(x))1538 1539 ## Now (May27,10) directly uses the model eval function1540 ## instead of the for-loop in Base Component.1541 def evalDistribution(self, x = []):1542 self._set_scale_factor()1543 return self.params['scale_factor'] %s \1544 (self.p_model1.evalDistribution(x) %s \1545 self.p_model2.evalDistribution(x))1546 1547 def set_dispersion(self, parameter, dispersion):1548 value= None1549 new_pre = parameter.split("_", 1)[0]1550 new_parameter = parameter.split("_", 1)[1]1551 try:1552 if new_pre == 'p1' and \1553 new_parameter in self.p_model1.dispersion.keys():1554 value= self.p_model1.set_dispersion(new_parameter, dispersion)1555 if new_pre == 'p2' and \1556 new_parameter in self.p_model2.dispersion.keys():1557 value= self.p_model2.set_dispersion(new_parameter, dispersion)1558 self._set_dispersion()1559 return value1560 except:1561 raise1562 1563 def fill_description(self, p_model1, p_model2):1564 description = ""1565 description += "This model gives the summation or multiplication of"1566 description += "%s and %s. "% ( p_model1.name, p_model2.name )1567 self.description += description1568 1569 if __name__ == "__main__":1570 m1= Model()1571 #m1.setParam("p1_scale", 25)1572 #m1.setParam("p1_length", 1000)1573 #m1.setParam("p2_scale", 100)1574 #m1.setParam("p2_rg", 100)1575 out1 = m1.runXY(0.01)1576 1577 m2= Model()1578 #m2.p_model1.setParam("scale", 25)1579 #m2.p_model1.setParam("length", 1000)1580 #m2.p_model2.setParam("scale", 100)1581 #m2.p_model2.setParam("rg", 100)1582 out2 = m2.p_model1.runXY(0.01) %s m2.p_model2.runXY(0.01)\n1583 print "My name is %s."% m1.name1584 print out1, " = ", out21585 if out1 == out2:1586 print "===> Simple Test: Passed!"1587 else:1588 print "===> Simple Test: Failed!"1589 """1590 1591 if __name__ == "__main__":1592 # app = wx.PySimpleApp()1593 1163 main_app = wx.App() 1594 1164 main_frame = TextDialog(id=1, model_list=["SphereModel", "CylinderModel"], 1595 plugin_dir='../fitting/plugin_models')1165 plugin_dir='../fitting/plugin_models') 1596 1166 main_frame.ShowModal() 1597 1167 main_app.MainLoop() 1598 1599 #if __name__ == "__main__":1600 # from sas.sasgui.perspectives.fitting import models1601 # dir_path = models.find_plugins_dir()1602 # app = wx.App()1603 # window = EditorWindow(parent=None, base=None, path=dir_path, title="Editor")1604 # app.MainLoop() -
src/sas/sasgui/perspectives/calculator/pyconsole.py
r7432acb r4627657 37 37 Iqxy = model.evalDistribution([qx, qy]) 38 38 39 result = """ 40 Iq(%s) = %s 41 Iqxy(%s, %s) = %s 42 """%(q, Iq, qx, qy, Iqxy) 39 # check the model's unit tests run 40 from sasmodels.model_test import run_one 41 result = run_one(path) 43 42 44 43 return result … … 89 88 ok = wx.Button(self, wx.ID_OK, "OK") 90 89 91 # Mysterious constraint layouts from 90 # Mysterious constraint layouts from 92 91 # https://www.wxpython.org/docs/api/wx.lib.layoutf.Layoutf-class.html 93 92 lc = layoutf.Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)) -
src/sas/sasgui/perspectives/calculator/resolution_calculator_panel.py
r7432acb r01cda57 934 934 def _sigma_strings(self): 935 935 """ 936 Recode sigmas as strin s936 Recode sigmas as strings 937 937 """ 938 938 sigma_r = self.format_number(self.resolution.sigma_1) … … 1208 1208 source_hint += "Mass of %s: m = %s [g]" % \ 1209 1209 (selection, str(self.resolution.get_neutron_mass())) 1210 # source_tip.SetTip(source_hint)1210 # source_tip.SetTip(source_hint) 1211 1211 self.mass_txt.ToolTip.SetTip(source_hint) 1212 1212
Note: See TracChangeset
for help on using the changeset viewer.