Changeset 2f5c49d in sasview
- Timestamp:
- Sep 13, 2017 8:18:48 AM (7 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 23359ccb
- Parents:
- 3b0f8cc (diff), 7b3f154 (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. - Files:
-
- 3 added
- 7 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
.pydevproject
r26c8be3 r9d93c37 4 4 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property> 5 5 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> 6 <path>/sasview 4/src</path>6 <path>/sasview/src</path> 7 7 </pydev_pathproperty> 8 8 </pydev_project> -
src/sas/sascalc/dataloader/data_info.py
r5a8cdbb r17e257b5 1161 1161 final_dataset = None 1162 1162 if isinstance(data, plottable_1D): 1163 final_dataset = Data1D(data.x, data.y )1163 final_dataset = Data1D(data.x, data.y, isSesans=datainfo.isSesans) 1164 1164 final_dataset.dx = data.dx 1165 1165 final_dataset.dy = data.dy 1166 1166 final_dataset.dxl = data.dxl 1167 1167 final_dataset.dxw = data.dxw 1168 final_dataset.x_unit = data._xunit 1169 final_dataset.y_unit = data._yunit 1168 1170 final_dataset.xaxis(data._xaxis, data._xunit) 1169 1171 final_dataset.yaxis(data._yaxis, data._yunit) -
src/sas/sascalc/dataloader/file_reader_base_class.py
rdcb91cf ra78a02f 6 6 7 7 import os 8 import re 8 9 import logging 9 10 import numpy as np … … 106 107 for data in self.output: 107 108 if isinstance(data, Data1D): 109 # Normalize the units for 110 data.x_unit = self.format_unit(data.x_unit) 111 data.y_unit = self.format_unit(data.y_unit) 108 112 # Sort data by increasing x and remove 1st point 109 113 ind = np.lexsort((data.y, data.x)) … … 131 135 for dataset in self.output: 132 136 if isinstance(dataset, Data2D): 137 # Normalize the units for 138 dataset.x_unit = self.format_unit(dataset.Q_unit) 139 dataset.y_unit = self.format_unit(dataset.I_unit) 133 140 dataset.data = dataset.data.astype(np.float64) 134 141 dataset.qx_data = dataset.qx_data.astype(np.float64) … … 155 162 dataset.data = dataset.data.flatten() 156 163 164 def format_unit(self, unit=None): 165 """ 166 Format units a common way 167 :param unit: 168 :return: 169 """ 170 if unit: 171 split = unit.split("/") 172 if len(split) == 1: 173 return unit 174 elif split[0] == '1': 175 return "{0}^".format(split[1]) + "{-1}" 176 else: 177 return "{0}*{1}^".format(split[0], split[1]) + "{-1}" 178 157 179 def set_all_to_none(self): 158 180 """ -
src/sas/sascalc/dataloader/readers/cansas_reader.py
rdcb91cf ra78a02f 299 299 self.current_dataset.dx = np.append(self.current_dataset.dx, data_point) 300 300 elif tagname == 'dQw': 301 if self.current_dataset.dqw is None: self.current_dataset.dqw = np.empty(0) 301 if self.current_dataset.dxw is None: 302 self.current_dataset.dxw = np.empty(0) 302 303 self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point) 303 304 elif tagname == 'dQl': 304 if self.current_dataset.dxl is None: self.current_dataset.dxl = np.empty(0) 305 if self.current_dataset.dxl is None: 306 self.current_dataset.dxl = np.empty(0) 305 307 self.current_dataset.dxl = np.append(self.current_dataset.dxl, data_point) 306 308 elif tagname == 'Qmean': -
src/sas/sascalc/dataloader/readers/danse_reader.py
r713a047 ra78a02f 189 189 x_vals = np.tile(x_vals, (size_y, 1)).flatten() 190 190 y_vals = np.tile(y_vals, (size_x, 1)).T.flatten() 191 if self.current_dataset.err_data == np.all(np.array(None)) or np.any(self.current_dataset.err_data <= 0): 191 if (np.all(self.current_dataset.err_data == None) 192 or np.any(self.current_dataset.err_data <= 0)): 192 193 new_err_data = np.sqrt(np.abs(self.current_dataset.data)) 193 194 else: -
src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py
r235f514 r2d9526d 14 14 import wx 15 15 import sys 16 from copy import deepcopy 16 17 from sas.sasgui.guiframe.events import EVT_NEW_PLOT 17 18 from sas.sasgui.guiframe.events import EVT_PLOT_QRANGE … … 275 276 action_check = True 276 277 else: 278 if action_string == 'update': 279 # Update all existing plots of data with this ID 280 for data in event.plots: 281 for panel in self.plot_panels.values(): 282 if data.id in panel.plots.keys(): 283 plot_exists = True 284 # Pass each panel it's own copy of the data 285 # that's being updated, otherwise things like 286 # colour and line thickness are unintentionally 287 # synced across panels 288 self.update_panel(deepcopy(data), panel) 289 return 290 277 291 group_id = event.group_id 278 if group_id in self.plot_panels .keys():292 if group_id in self.plot_panels: 279 293 #remove data from panel 280 294 if action_string == 'remove': -
src/sas/sasgui/perspectives/fitting/fitting.py
r489f53a r2d9526d 1742 1742 @param unsmeared_error: data error, rescaled to unsmeared model 1743 1743 """ 1744 1745 1744 number_finite = np.count_nonzero(np.isfinite(y)) 1746 1745 np.nan_to_num(y) … … 1748 1747 data_description=model.name, 1749 1748 data_id=str(page_id) + " " + data.name) 1749 plots_to_update = [] # List of plottables that have changed since last calculation 1750 # Create the new theories 1750 1751 if unsmeared_model is not None: 1751 self.create_theory_1D(x, unsmeared_model, page_id, model, data, state, 1752 unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 1753 page_id, model, data, state, 1752 1754 data_description=model.name + " unsmeared", 1753 1755 data_id=str(page_id) + " " + data.name + " unsmeared") 1756 plots_to_update.append(unsmeared_model_plot) 1754 1757 1755 1758 if unsmeared_data is not None and unsmeared_error is not None: 1756 self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 1759 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 1760 page_id, model, data, state, 1757 1761 data_description="Data unsmeared", 1758 1762 data_id="Data " + data.name + " unsmeared", 1759 1763 dy=unsmeared_error) 1760 # Comment this out until we can get P*S models with correctly populated parameters 1761 #if sq_model is not None and pq_model is not None: 1762 # self.create_theory_1D(x, sq_model, page_id, model, data, state, 1763 # data_description=model.name + " S(q)", 1764 # data_id=str(page_id) + " " + data.name + " S(q)") 1765 # self.create_theory_1D(x, pq_model, page_id, model, data, state, 1766 # data_description=model.name + " P(q)", 1767 # data_id=str(page_id) + " " + data.name + " P(q)") 1764 plots_to_update.append(unsmeared_data_plot) 1765 if sq_model is not None and pq_model is not None: 1766 sq_id = str(page_id) + " " + data.name + " S(q)" 1767 sq_plot = self.create_theory_1D(x, sq_model, page_id, model, data, state, 1768 data_description=model.name + " S(q)", 1769 data_id=sq_id) 1770 plots_to_update.append(sq_plot) 1771 pq_id = str(page_id) + " " + data.name + " P(q)" 1772 pq_plot = self.create_theory_1D(x, pq_model, page_id, model, data, state, 1773 data_description=model.name + " P(q)", 1774 data_id=pq_id) 1775 plots_to_update.append(pq_plot) 1776 # Update the P(Q), S(Q) and unsmeared theory plots if they exist 1777 wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 1778 action='update')) 1768 1779 1769 1780 current_pg = self.fit_panel.get_page_by_id(page_id) -
src/sas/sasgui/perspectives/fitting/media/fitting_help.rst
r5295cf5 r05b0bf6 484 484 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 485 485 486 .. _Batch_Fit_Mode: 487 486 488 Batch Fit Mode 487 489 -------------- … … 636 638 637 639 Example: radius [2 : 5] , radius [10 : 25] 638 639 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 640 641 .. note:: This help document was last changed by Steve King, 10Oct2016 640 641 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 642 643 Combined Batch Fit Mode 644 ----------------------- 645 646 The purpose of the Combined Batch Fit is to allow running two or more batch 647 fits in sequence without overwriting the output table of results. This may be 648 of interest for example if one is fitting a series of data sets where there is 649 a shape change occurring in the series that requires changing the model part 650 way through the series; for example a sphere to rod transition. Indeed the 651 regular batch mode does not allow for multiple models and requires all the 652 files in the series to be fit with single model and set of parameters. While 653 it is of course possible to just run part of the series as a batch fit using 654 model one followed by running another batch fit on the rest of the series with 655 model two (and/or model three etc), doing so will overwrite the table of 656 outputs from the previous batch fit(s). This may not be desirable if one is 657 interested in comparing the parameters: for example the sphere radius of set 658 one and the cylinder radius of set two. 659 660 Method 661 ^^^^^^ 662 663 In order to use the *Combined Batch Fit*, first load all the data needed as 664 described in :ref:`Loading_data`. Next start up two or more *BatchPage* fits 665 following the instructions in :ref:`Batch_Fit_Mode` but **DO NOT PRESS FIT**. 666 At this point the *Combine Batch Fit* menu item under the *Fitting menu* should 667 be active (if there is one or no *BatchPage* the menu item will be greyed out 668 and inactive). Clicking on *Combine Batch Fit* will bring up a new panel, 669 similar to the *Const & Simult Fit* panel. In this case there will be a 670 checkbox for each *BatchPage* instead of each *FitPage* that should be included 671 in the fit. Once all are selected, click the Fit button on 672 the *BatchPage* to run each batch fit in *sequence* 673 674 .. image:: combine_batch_page.png 675 676 The batch table will then pop up at the end as for the case of the simple Batch 677 Fitting with the following caveats: 678 679 .. note:: 680 The order matters. The parameters in the table will be taken from the model 681 used in the first *BatchPage* of the list. Any parameters from the 682 second and later *BatchPage* s that have the same name as a parameter in the 683 first will show up allowing for plotting of that parameter across the 684 models. The other parameters will not be available in the grid. 685 .. note:: 686 a corralary of the above is that currently models created as a sum|multiply 687 model will not work as desired because the generated model parameters have a 688 p#_ appended to the beginning and thus radius and p1_radius will not be 689 recognized as the same parameter. 690 691 .. image:: combine_batch_grid.png 692 693 In the example shown above the data is a time series with a shifting peak. 694 The first part of the series was fitted using the *broad_peak* model, while 695 the rest of the data were fit using the *gaussian_peak* model. Unfortunately the 696 time is not listed in the file but the file name contains the information. As 697 described in :ref:`Grid_Window`, a column can be added manually, in this case 698 called time, and the peak position plotted against time. 699 700 .. image:: combine_batch_plot.png 701 702 Note the discontinuity in the peak position. This reflects the fact that the 703 Gaussian fit is a rather poor model for the data and is not actually 704 finding the peak. 705 706 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 707 708 .. note:: This help document was last changed by Paul Butler, 10 September 709 2017 -
src/sas/sasgui/perspectives/fitting/model_thread.py
r7432acb r0f9ea1c 71 71 (self.data.qy_data * self.data.qy_data)) 72 72 73 # For theory, qmax is based on 1d qmax 73 # For theory, qmax is based on 1d qmax 74 74 # so that must be mulitified by sqrt(2) to get actual max for 2d 75 75 index_model = (self.qmin <= radius) & (radius <= self.qmax) … … 91 91 self.data.qy_data[index_model] 92 92 ]) 93 output = np.zeros(len(self.data.qx_data)) 93 # Initialize output to NaN so masked elements do not get plotted. 94 output = np.empty_like(self.data.qx_data) 94 95 # output default is None 95 96 # This method is to distinguish between masked 96 97 #point(nan) and data point = 0. 97 output = output / output98 output[:] = np.NaN 98 99 # set value for self.mask==True, else still None to Plottools 99 100 output[index_model] = value … … 198 199 output[index] = self.model.evalDistribution(self.data.x[index]) 199 200 201 x=self.data.x[index] 202 y=output[index] 200 203 sq_values = None 201 204 pq_values = None 202 s_model = None203 p_model = None204 205 if isinstance(self.model, MultiplicationModel): 205 206 s_model = self.model.s_model 206 207 p_model = self.model.p_model 207 elif hasattr(self.model, "get_composition_models"): 208 p_model, s_model = self.model.get_composition_models() 209 210 if p_model is not None and s_model is not None: 211 sq_values = np.zeros((len(self.data.x))) 212 pq_values = np.zeros((len(self.data.x))) 213 sq_values[index] = s_model.evalDistribution(self.data.x[index]) 214 pq_values[index] = p_model.evalDistribution(self.data.x[index]) 208 sq_values = s_model.evalDistribution(x) 209 pq_values = p_model.evalDistribution(x) 210 elif hasattr(self.model, "calc_composition_models"): 211 results = self.model.calc_composition_models(x) 212 if results is not None: 213 pq_values, sq_values = results 214 215 215 216 216 elapsed = time.time() - self.starttime 217 217 218 self.complete(x= self.data.x[index], y=output[index],218 self.complete(x=x, y=y, 219 219 page_id=self.page_id, 220 220 state=self.state, -
src/sas/sasgui/perspectives/fitting/simfitpage.py
r959eb01 ra9f9ca4 1 1 """ 2 Simultaneous fit page2 Simultaneous or Batch fit page 3 3 """ 4 # Note that this is used for both Simultaneous/Constrained fit AND for 5 # combined batch fit. This is done through setting of the batch_on parameter. 6 # There are the a half dozen or so places where an if statement is used as in 7 # if not batch_on: 8 # xxxx 9 # else: 10 # xxxx 11 # This is just wrong but dont have time to fix this go. Proper approach would be 12 # to strip all parts of the code that depend on batch_on and create the top 13 # level class from which a contrained/simultaneous fit page and a combined 14 # batch page inherit. 15 # 16 # 04/09/2017 --PDB 17 4 18 import sys 5 19 from collections import namedtuple … … 400 414 # General Help button 401 415 self.btHelp = wx.Button(self, wx.ID_HELP, 'HELP') 402 self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 416 if self.batch_on: 417 self.btHelp.SetToolTipString("Combined Batch Fitting help.") 418 else: 419 self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 403 420 self.btHelp.Bind(wx.EVT_BUTTON, self._on_help) 404 421 … … 527 544 """ 528 545 _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 529 _PageAnchor = "#simultaneous-fit-mode" 530 _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 546 if not self.batch_on: 547 _PageAnchor = "#simultaneous-fit-mode" 548 _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 531 549 _PageAnchor, 532 550 "Simultaneous/Constrained Fitting Help") 551 else: 552 _PageAnchor = "#combined-batch-fit-mode" 553 _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 554 _PageAnchor, 555 "Combined Batch Fit Help") 533 556 534 557 def set_manager(self, manager): -
src/sas/sasgui/plottools/plottables.py
r45dffa69 r2d9526d 239 239 def replace(self, plottable): 240 240 """Replace an existing plottable from the graph""" 241 selected_color = None 241 # If the user has set a custom color, ensure the new plot is the same color 242 selected_color = plottable.custom_color 242 243 selected_plottable = None 243 244 for p in self.plottables.keys(): 244 245 if plottable.id == p.id: 245 246 selected_plottable = p 246 selected_color = self.plottables[p] 247 if selected_color is None: 248 selected_color = self.plottables[p] 247 249 break 248 if 250 if selected_plottable is not None and selected_color is not None: 249 251 del self.plottables[selected_plottable] 252 plottable.custom_color = selected_color 250 253 self.plottables[plottable] = selected_color 251 254 -
test/sasdataloader/test/utest_abs_reader.py
rce8c7bd ra78a02f 20 20 def setUp(self): 21 21 reader = AbsReader() 22 self.data = reader.read("jan08002.ABS") 22 data = reader.read("jan08002.ABS") 23 self.data= data[0] 23 24 24 25 def test_abs_checkdata(self): … … 47 48 self.assertEqual(self.data.detector[0].beam_center.y, center_y) 48 49 49 self.assertEqual(self.data.y_unit, ' 1/cm')50 self.assertEqual(self.data.y_unit, 'cm^{-1}') 50 51 self.assertEqual(self.data.x[0], 0.002618) 51 52 self.assertEqual(self.data.x[1], 0.007854) … … 69 70 # the generic loader should work as well 70 71 data = Loader().load("jan08002.ABS") 71 self.assertEqual(data .meta_data['loader'], "IGOR 1D")72 self.assertEqual(data[0].meta_data['loader'], "IGOR 1D") 72 73 73 74 class DanseReaderTests(unittest.TestCase): … … 75 76 def setUp(self): 76 77 reader = DANSEReader() 77 self.data = reader.read("MP_New.sans") 78 data = reader.read("MP_New.sans") 79 self.data = data[0] 78 80 79 81 def test_checkdata(self): … … 112 114 # the generic loader should work as well 113 115 data = Loader().load("MP_New.sans") 114 self.assertEqual(data .meta_data['loader'], "DANSE")116 self.assertEqual(data[0].meta_data['loader'], "DANSE") 115 117 116 118 … … 144 146 # Data 145 147 self.assertEqual(len(self.data.x), 2) 146 self.assertEqual(self.data.x_unit, ' 1/A')147 self.assertEqual(self.data.y_unit, ' 1/cm')148 self.assertEqual(self.data.x_unit, 'A^{-1}') 149 self.assertEqual(self.data.y_unit, 'cm^{-1}') 148 150 self.assertAlmostEqual(self.data.x[0], 0.02, 6) 149 151 self.assertAlmostEqual(self.data.y[0], 1000, 6) … … 257 259 self.assertTrue(item.date in ['04-Sep-2007 18:35:02', 258 260 '03-SEP-2006 11:42:47']) 259 print(item.term)260 261 for t in item.term: 261 262 if (t['name'] == "ABS:DSTAND" … … 309 310 310 311 self.assertEqual(self.data.meta_data['loader'], "CanSAS XML 1D") 311 print(self.data.errors) 312 self.assertEqual(len(self.data.errors), 1) 312 self.assertEqual(len(self.data.errors), 0) 313 313 314 314 def test_slits(self): … … 324 324 # Data 325 325 self.assertEqual(len(self.data.x), 2) 326 self.assertEqual(self.data.x_unit, ' 1/A')327 self.assertEqual(self.data.y_unit, ' 1/cm')326 self.assertEqual(self.data.x_unit, 'A^{-1}') 327 self.assertEqual(self.data.y_unit, 'cm^{-1}') 328 328 self.assertEqual(self.data.x[0], 0.02) 329 329 self.assertEqual(self.data.y[0], 1000) … … 333 333 self.assertEqual(self.data.x[1], 0.03) 334 334 self.assertAlmostEquals(self.data.y[1], 1001.0) 335 self.assertEqual(self.data.dx , None)335 self.assertEqual(self.data.dx[0], 0.0) 336 336 self.assertEqual(self.data.dxl[1], 0.005) 337 337 self.assertEqual(self.data.dxw[1], 0.001) -
test/sasdataloader/test/utest_ascii.py
rad92c5a ra78a02f 32 32 self.assertEqual(self.f1.x[0],0.002618) 33 33 self.assertEqual(self.f1.x[9],0.0497) 34 self.assert Equal(self.f1.x_unit, '1/A')35 self.assert Equal(self.f1.y_unit, '1/cm')34 self.assertTrue(self.f1.x_unit == 'A^{-1}') 35 self.assertTrue(self.f1.y_unit == 'cm^{-1}') 36 36 37 37 self.assertEqual(self.f1.meta_data['loader'],"ASCII") -
test/sasdataloader/test/utest_cansas.py
r1fc50fb2 r17e257b5 20 20 21 21 from lxml import etree 22 from lxml.etree import XMLSyntaxError 22 23 from xml.dom import minidom 23 24 … … 62 63 """ 63 64 invalid = StringIO.StringIO('<a><c></b></a>') 64 XMLreader(invalid)65 self.assertRaises(XMLSyntaxError, lambda: XMLreader(invalid)) 65 66 66 67 def test_xml_validate(self): … … 302 303 self.assertTrue(data._yunit == "cm^{-1}") 303 304 self.assertTrue(data.y.size == 100) 304 self.assertAlmostEqual(data.y[ 9], 0.952749011516985)305 self.assertAlmostEqual(data.x[ 9], 0.3834415188257777)305 self.assertAlmostEqual(data.y[40], 0.952749011516985) 306 self.assertAlmostEqual(data.x[40], 0.3834415188257777) 306 307 self.assertAlmostEqual(len(data.meta_data), 0) 307 308 -
test/sasdataloader/test/utest_sesans.py
ra67c494 ra78a02f 4 4 5 5 import unittest 6 from sas.sascalc.dataloader.loader_exceptions import FileContentsException,\ 7 DefaultReaderException 6 8 from sas.sascalc.dataloader.readers.sesans_reader import Reader 7 9 from sas.sascalc.dataloader.loader import Loader … … 17 19 Test .SES in the full loader to make sure that the file type is correctly accepted 18 20 """ 19 f = Loader().load("sesans_examples/sphere2micron.ses") 21 file = Loader().load("sesans_examples/sphere2micron.ses") 22 f = file[0] 20 23 # self.assertEqual(f, 5) 21 24 self.assertEqual(len(f.x), 40) … … 34 37 Test .SES loading on a TOF dataset 35 38 """ 36 f = self.loader("sesans_examples/sphere_isis.ses") 39 file = self.loader("sesans_examples/sphere_isis.ses") 40 f = file[0] 37 41 self.assertEqual(len(f.x), 57) 38 42 self.assertEqual(f.x[-1], 19303.4) … … 48 52 """ 49 53 self.assertRaises( 50 RuntimeError,54 FileContentsException, 51 55 self.loader, 52 56 "sesans_examples/sesans_no_data.ses") … … 57 61 """ 58 62 self.assertRaises( 59 RuntimeError,63 FileContentsException, 60 64 self.loader, 61 65 "sesans_examples/no_spin_echo_unit.ses") 62 63 def test_sesans_no_version(self):64 """65 Confirm that sesans files with no file format version raise an appropriate error66 """67 self.assertRaises(68 RuntimeError,69 self.loader,70 "sesans_examples/no_version.ses")71 66 72 67 def test_sesans_future_version(self): … … 75 70 """ 76 71 self.assertRaises( 77 RuntimeError,72 FileContentsException, 78 73 self.loader, 79 74 "sesans_examples/next_gen.ses") … … 84 79 """ 85 80 self.assertRaises( 86 RuntimeError,81 FileContentsException, 87 82 self.loader, 88 83 "sesans_examples/no_wavelength.ses") … … 93 88 """ 94 89 self.assertRaises( 95 RuntimeError,90 FileContentsException, 96 91 self.loader, 97 92 "sesans_examples/too_many_headers.ses") -
test/utest_sasview.py
raaf5e49 rb54440d 44 44 n_errors = 0 45 45 n_failures = 0 46 46 47 47 for d in (dirs if dirs else os.listdir(test_root)): 48 48 49 49 # Check for modules to be skipped 50 50 if d in SKIPPED_DIRS: 51 51 continue 52 52 53 53 54 54 # Go through modules looking for unit tests … … 64 64 #print std_out 65 65 #sys.exit() 66 has_failed = True67 66 m = re.search("Ran ([0-9]+) test", std_out) 68 67 if m is not None: 69 has_failed = False70 68 n_tests += int(m.group(1)) 69 has_tests = True 70 else: 71 has_tests = False 71 72 72 m = re.search("FAILED \(errors=([0-9]+)\)", std_out) 73 has_failed = "FAILED (" in std_out 74 m = re.search("FAILED \(.*errors=([0-9]+)", std_out) 73 75 if m is not None: 74 has_failed = True75 76 n_errors += int(m.group(1)) 76 77 m = re.search("FAILED \(failures=([0-9]+)\)", std_out) 77 m = re.search("FAILED \(.*failures=([0-9]+)", std_out) 78 78 if m is not None: 79 has_failed = True80 79 n_failures += int(m.group(1)) 81 82 if has_failed :80 81 if has_failed or not has_tests: 83 82 failed += 1 84 83 print("Result for %s (%s): FAILED" % (module_name, module_dir)) … … 102 101 print(" Test errors: %d" % n_errors) 103 102 print("----------------------------------------------") 104 103 105 104 return failed 106 105 … … 110 109 if run_tests(dirs=dirs, all=all)>0: 111 110 sys.exit(1) 112 111 -
sasview/sasview.py
rf36e01f r3b0f8cc 74 74 PLUGIN_MODEL_DIR = 'plugin_models' 75 75 APP_NAME = 'SasView' 76 77 # Set SAS_MODELPATH so sasmodels can find our custom models 78 os.environ['SAS_MODELPATH'] = os.path.join(sasdir, PLUGIN_MODEL_DIR) 76 79 77 80 from matplotlib import backend_bases -
src/sas/sasgui/perspectives/calculator/model_editor.py
r07ec714 rc351bf1 106 106 self.model2_string = "cylinder" 107 107 self.name = 'Sum' + M_NAME 108 self.factor = 'scale_factor'109 108 self._notes = '' 110 109 self._operator = '+' … … 133 132 self.model2_name = str(self.model2.GetValue()) 134 133 self.good_name = True 135 self.fill_op rator_combox()134 self.fill_operator_combox() 136 135 137 136 def _layout_name(self): … … 491 490 a sum or multiply model then create the appropriate string 492 491 """ 493 494 492 name = '' 495 496 493 if operator == '*': 497 494 name = 'Multi' 498 factor = 'BackGround' 499 f_oper = '+' 495 factor = 'background' 500 496 else: 501 497 name = 'Sum' 502 498 factor = 'scale_factor' 503 f_oper = '*' 504 505 self.factor = factor 499 506 500 self._operator = operator 507 self.explanation = " Plugin Model = %s %s (model1 %s model2)\n" % \508 (self.factor, f_oper, self._operator)501 self.explanation = (" Plugin_model = scale_factor * (model_1 {} " 502 "model_2) + background").format(operator) 509 503 self.explanationctr.SetLabel(self.explanation) 510 504 self.name = name + M_NAME 511 505 512 506 513 def fill_op rator_combox(self):507 def fill_operator_combox(self): 514 508 """ 515 509 fill the current combobox with the operator … … 527 521 return [self.model1_name, self.model2_name] 528 522 529 def write_string(self, fname, name1, name2):523 def write_string(self, fname, model1_name, model2_name): 530 524 """ 531 525 Write and Save file … … 533 527 self.fname = fname 534 528 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." 529 desc_line = '' 530 if description.strip() != '': 531 # Sasmodels generates a description for us. If the user provides 532 # their own description, add a line to overwrite the sasmodels one 533 desc_line = "\nmodel_info.description = '{}'".format(description) 534 name = os.path.splitext(os.path.basename(self.fname))[0] 535 output = SUM_TEMPLATE.format(name=name, model1=model1_name, 536 model2=model2_name, operator=self._operator, desc_line=desc_line) 537 with open(self.fname, 'w') as out_f: 538 out_f.write(output) 606 539 607 540 def compile_file(self, path): … … 1278 1211 """ 1279 1212 SUM_TEMPLATE = """ 1280 # A sample of an experimental model function for Sum/Multiply(Pmodel1,Pmodel2) 1281 import os 1282 import sys 1283 import copy 1284 import collections 1285 1286 import numpy 1287 1288 from sas.sascalc.fit.pluginmodel import Model1DPlugin 1289 from sasmodels.sasview_model import find_model 1290 1291 class Model(Model1DPlugin): 1292 name = os.path.splitext(os.path.basename(__file__))[0] 1293 is_multiplicity_model = False 1294 def __init__(self, multiplicity=1): 1295 Model1DPlugin.__init__(self, name='') 1296 P1 = find_model('%s') 1297 P2 = find_model('%s') 1298 p_model1 = P1() 1299 p_model2 = P2() 1300 ## Setting model name model description 1301 self.description = '%s' 1302 if self.name.rstrip().lstrip() == '': 1303 self.name = self._get_name(p_model1.name, p_model2.name) 1304 if self.description.rstrip().lstrip() == '': 1305 self.description = p_model1.name 1306 self.description += p_model2.name 1307 self.fill_description(p_model1, p_model2) 1308 1309 ## Define parameters 1310 self.params = collections.OrderedDict() 1311 1312 ## Parameter details [units, min, max] 1313 self.details = {} 1314 ## Magnetic Panrameters 1315 self.magnetic_params = [] 1316 # non-fittable parameters 1317 self.non_fittable = p_model1.non_fittable 1318 self.non_fittable += p_model2.non_fittable 1319 1320 ##models 1321 self.p_model1= p_model1 1322 self.p_model2= p_model2 1323 1324 1325 ## dispersion 1326 self._set_dispersion() 1327 ## Define parameters 1328 self._set_params() 1329 ## New parameter:scaling_factor 1330 self.params['scale_factor'] = %s 1331 1332 ## Parameter details [units, min, max] 1333 self._set_details() 1334 self.details['scale_factor'] = ['', 0.0, numpy.inf] 1335 1336 1337 #list of parameter that can be fitted 1338 self._set_fixed_params() 1339 1340 ## parameters with orientation 1341 self.orientation_params = [] 1342 for item in self.p_model1.orientation_params: 1343 new_item = "p1_" + item 1344 if not new_item in self.orientation_params: 1345 self.orientation_params.append(new_item) 1346 1347 for item in self.p_model2.orientation_params: 1348 new_item = "p2_" + item 1349 if not new_item in self.orientation_params: 1350 self.orientation_params.append(new_item) 1351 ## magnetic params 1352 self.magnetic_params = [] 1353 for item in self.p_model1.magnetic_params: 1354 new_item = "p1_" + item 1355 if not new_item in self.magnetic_params: 1356 self.magnetic_params.append(new_item) 1357 1358 for item in self.p_model2.magnetic_params: 1359 new_item = "p2_" + item 1360 if not new_item in self.magnetic_params: 1361 self.magnetic_params.append(new_item) 1362 # get multiplicity if model provide it, else 1. 1363 try: 1364 multiplicity1 = p_model1.multiplicity 1365 try: 1366 multiplicity2 = p_model2.multiplicity 1367 except: 1368 multiplicity2 = 1 1369 except: 1370 multiplicity1 = 1 1371 multiplicity2 = 1 1372 ## functional multiplicity of the model 1373 self.multiplicity1 = multiplicity1 1374 self.multiplicity2 = multiplicity2 1375 self.multiplicity_info = [] 1376 1377 def _clone(self, obj): 1378 import copy 1379 obj.params = copy.deepcopy(self.params) 1380 obj.description = copy.deepcopy(self.description) 1381 obj.details = copy.deepcopy(self.details) 1382 obj.dispersion = copy.deepcopy(self.dispersion) 1383 obj.p_model1 = self.p_model1.clone() 1384 obj.p_model2 = self.p_model2.clone() 1385 #obj = copy.deepcopy(self) 1386 return obj 1387 1388 def _get_name(self, name1, name2): 1389 p1_name = self._get_upper_name(name1) 1390 if not p1_name: 1391 p1_name = name1 1392 name = p1_name 1393 name += "_and_" 1394 p2_name = self._get_upper_name(name2) 1395 if not p2_name: 1396 p2_name = name2 1397 name += p2_name 1398 return name 1399 1400 def _get_upper_name(self, name=None): 1401 if name is None: 1402 return "" 1403 upper_name = "" 1404 str_name = str(name) 1405 for index in range(len(str_name)): 1406 if str_name[index].isupper(): 1407 upper_name += str_name[index] 1408 return upper_name 1409 1410 def _set_dispersion(self): 1411 self.dispersion = collections.OrderedDict() 1412 ##set dispersion only from p_model 1413 for name , value in self.p_model1.dispersion.iteritems(): 1414 #if name.lower() not in self.p_model1.orientation_params: 1415 new_name = "p1_" + name 1416 self.dispersion[new_name]= value 1417 for name , value in self.p_model2.dispersion.iteritems(): 1418 #if name.lower() not in self.p_model2.orientation_params: 1419 new_name = "p2_" + name 1420 self.dispersion[new_name]= value 1421 1422 def function(self, x=0.0): 1423 return 0 1424 1425 def getProfile(self): 1426 try: 1427 x,y = self.p_model1.getProfile() 1428 except: 1429 x = None 1430 y = None 1431 1432 return x, y 1433 1434 def _set_params(self): 1435 for name , value in self.p_model1.params.iteritems(): 1436 # No 2D-supported 1437 #if name not in self.p_model1.orientation_params: 1438 new_name = "p1_" + name 1439 self.params[new_name]= value 1440 1441 for name , value in self.p_model2.params.iteritems(): 1442 # No 2D-supported 1443 #if name not in self.p_model2.orientation_params: 1444 new_name = "p2_" + name 1445 self.params[new_name]= value 1446 1447 # Set "scale" as initializing 1448 self._set_scale_factor() 1449 1450 1451 def _set_details(self): 1452 for name ,detail in self.p_model1.details.iteritems(): 1453 new_name = "p1_" + name 1454 #if new_name not in self.orientation_params: 1455 self.details[new_name]= detail 1456 1457 for name ,detail in self.p_model2.details.iteritems(): 1458 new_name = "p2_" + name 1459 #if new_name not in self.orientation_params: 1460 self.details[new_name]= detail 1461 1462 def _set_scale_factor(self): 1463 pass 1464 1465 1466 def setParam(self, name, value): 1467 # set param to this (p1, p2) model 1468 self._setParamHelper(name, value) 1469 1470 ## setParam to p model 1471 model_pre = '' 1472 new_name = '' 1473 name_split = name.split('_', 1) 1474 if len(name_split) == 2: 1475 model_pre = name.split('_', 1)[0] 1476 new_name = name.split('_', 1)[1] 1477 if model_pre == "p1": 1478 if new_name in self.p_model1.getParamList(): 1479 self.p_model1.setParam(new_name, value) 1480 elif model_pre == "p2": 1481 if new_name in self.p_model2.getParamList(): 1482 self.p_model2.setParam(new_name, value) 1483 elif name == 'scale_factor': 1484 self.params['scale_factor'] = value 1485 else: 1486 raise ValueError, "Model does not contain parameter %s" % name 1487 1488 def getParam(self, name): 1489 # Look for dispersion parameters 1490 toks = name.split('.') 1491 if len(toks)==2: 1492 for item in self.dispersion.keys(): 1493 # 2D not supported 1494 if item.lower()==toks[0].lower(): 1495 for par in self.dispersion[item]: 1496 if par.lower() == toks[1].lower(): 1497 return self.dispersion[item][par] 1498 else: 1499 # Look for standard parameter 1500 for item in self.params.keys(): 1501 if item.lower()==name.lower(): 1502 return self.params[item] 1503 return 1504 #raise ValueError, "Model does not contain parameter %s" % name 1505 1506 def _setParamHelper(self, name, value): 1507 # Look for dispersion parameters 1508 toks = name.split('.') 1509 if len(toks)== 2: 1510 for item in self.dispersion.keys(): 1511 if item.lower()== toks[0].lower(): 1512 for par in self.dispersion[item]: 1513 if par.lower() == toks[1].lower(): 1514 self.dispersion[item][par] = value 1515 return 1516 else: 1517 # Look for standard parameter 1518 for item in self.params.keys(): 1519 if item.lower()== name.lower(): 1520 self.params[item] = value 1521 return 1522 1523 raise ValueError, "Model does not contain parameter %s" % name 1524 1525 1526 def _set_fixed_params(self): 1527 self.fixed = [] 1528 for item in self.p_model1.fixed: 1529 new_item = "p1" + item 1530 self.fixed.append(new_item) 1531 for item in self.p_model2.fixed: 1532 new_item = "p2" + item 1533 self.fixed.append(new_item) 1534 1535 self.fixed.sort() 1536 1537 1538 def run(self, x = 0.0): 1539 self._set_scale_factor() 1540 return self.params['scale_factor'] %s \ 1541 (self.p_model1.run(x) %s self.p_model2.run(x)) 1542 1543 def runXY(self, x = 0.0): 1544 self._set_scale_factor() 1545 return self.params['scale_factor'] %s \ 1546 (self.p_model1.runXY(x) %s self.p_model2.runXY(x)) 1547 1548 ## Now (May27,10) directly uses the model eval function 1549 ## instead of the for-loop in Base Component. 1550 def evalDistribution(self, x = []): 1551 self._set_scale_factor() 1552 return self.params['scale_factor'] %s \ 1553 (self.p_model1.evalDistribution(x) %s \ 1554 self.p_model2.evalDistribution(x)) 1555 1556 def set_dispersion(self, parameter, dispersion): 1557 value= None 1558 new_pre = parameter.split("_", 1)[0] 1559 new_parameter = parameter.split("_", 1)[1] 1560 try: 1561 if new_pre == 'p1' and \ 1562 new_parameter in self.p_model1.dispersion.keys(): 1563 value= self.p_model1.set_dispersion(new_parameter, dispersion) 1564 if new_pre == 'p2' and \ 1565 new_parameter in self.p_model2.dispersion.keys(): 1566 value= self.p_model2.set_dispersion(new_parameter, dispersion) 1567 self._set_dispersion() 1568 return value 1569 except: 1570 raise 1571 1572 def fill_description(self, p_model1, p_model2): 1573 description = "" 1574 description += "This model gives the summation or multiplication of" 1575 description += "%s and %s. "% ( p_model1.name, p_model2.name ) 1576 self.description += description 1577 1578 if __name__ == "__main__": 1579 m1= Model() 1580 #m1.setParam("p1_scale", 25) 1581 #m1.setParam("p1_length", 1000) 1582 #m1.setParam("p2_scale", 100) 1583 #m1.setParam("p2_rg", 100) 1584 out1 = m1.runXY(0.01) 1585 1586 m2= Model() 1587 #m2.p_model1.setParam("scale", 25) 1588 #m2.p_model1.setParam("length", 1000) 1589 #m2.p_model2.setParam("scale", 100) 1590 #m2.p_model2.setParam("rg", 100) 1591 out2 = m2.p_model1.runXY(0.01) %s m2.p_model2.runXY(0.01)\n 1592 print "My name is %s."% m1.name 1593 print out1, " = ", out2 1594 if out1 == out2: 1595 print "===> Simple Test: Passed!" 1596 else: 1597 print "===> Simple Test: Failed!" 1213 from sasmodels.core import load_model_info 1214 from sasmodels.sasview_model import make_model_from_info 1215 1216 model_info = load_model_info('{model1}{operator}{model2}', force_mixture=True) 1217 model_info.name = '{name}'{desc_line} 1218 Model = make_model_from_info(model_info) 1598 1219 """ 1599 1600 1220 if __name__ == "__main__": 1601 1221 # app = wx.PySimpleApp()
Note: See TracChangeset
for help on using the changeset viewer.