Changes in / [5156918:1a8e13f0] in sasview
- Files:
-
- 2 added
- 2 deleted
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
LICENSE.TXT
ra3e3ef5 r7c05b63 1 Copyright (c) 2009-201 7, SasView Developers1 Copyright (c) 2009-2016, SasView Developers 2 2 All rights reserved. 3 3 -
sasview/README.txt
r311d00a r220b1e7 4 4 1- Features 5 5 =========== 6 - New in Version 4.1.07 ------------------8 This incremental release brings a series of new features and improvements,9 and a host of bug fixes. Of particular note are:10 11 - Correlation Function Analysis (Corfunc)12 This performs a correlation function analysis of one-dimensional SAXS/SANS data,13 or generates a model-independent volume fraction profile from the SANS from an14 adsorbed polymer/surfactant layer.15 16 A correlation function may be interpreted in terms of an imaginary rod moving17 through the structure of the material. Î1D(R) is the probability that a rod of18 length R moving through the material has equal electron/neutron scattering19 length density at either end. Hence a frequently occurring spacing within a20 structure manifests itself as a peak.21 22 A volume fraction profile \Phi(z) describes how the density of polymer23 segments/surfactant molecules varies with distance from an (assumed locally flat)24 interface.25 26 - Fitting of SESANS Data27 Data from Spin-Echo SANS measurements can now be loaded and fitted. The data will28 be plotted against the correct axes and models will automatically perform a Hankel29 transform in order to calculate SESANS from a SANS model.30 31 - Documentation32 The documentation has undergone significant checking and updating.33 34 - Improvements35 - Correlation function (corfunc) analysis of 1D SAS data added from CCP1336 - File converter tool for multi-file single column data sets37 - SESANS data loading and direct fitting using the Hankel transformation38 - Saving and loading of simultaneous and constrained fits now supported39 - Save states from SasView v3.x.y now loaded using sasmodel model names40 - Saving and loading of projects with 2D fits now supported41 - Loading a project removes all existing data, fits, and plots42 - Structure factor and form factor can be plotted independently43 - OpenCL is disabled by default and can be enabled through a fit menu44 - Data and theory fields are now independently expandable45 - Bug Fixes46 - Fixes #667: Models computed multiple times on parameters changes47 - Fixes #673: Custom models override built in models of same name48 - Fixes #678: Hard crash when running complex models on GPU49 - Fixes $774: Old style plugin models unloadable50 - Fixes #789: stacked disk scale doesn't match cylinder model51 - Fixes #792: core_shell_fractal uses wrong effective radius52 - Fixes #800: Plot range reset on plot redraws53 - Fixes #811 and #825: 2D smearing broken54 - Fixes #815: Integer model parameter handling55 - Fixes #824: Cannot apply sector averaging when no detector data present56 - Fixes #830: Cansas HDF5 reader fully compliant with NXCanSAS v1.0 format57 - Fixes #835: Fractal model breaks with negative Q values58 - Fixes #843: Multilayer vesicle does not define effective radius59 - Fixes #858: Hayter MSA S(Q) returns errors60 - Numerous grammatical and contexual errors in documention61 62 63 6 - New in Version 4.0.1 64 7 ------------------ … … 483 426 =============== 484 427 485 486 4.1- All systems:487 The conversion to sasmodels infrastructure is ongoing and should be488 completed in the next release. In the meantime this leads to a few known489 issues:490 - The way that orientation is defined is being refactored to address491 long standing issues and comments. In release 4.1 however only models492 with symmetry (e.g. a=b) have been converted to the new definitions.493 The rest (a <> b <> c - e.g. parellelepiped) maintain the same494 definition as before and will be converted in 4.2. Note that495 orientational distribution also makes much more sense in the new496 framework. The documentation should indicate which definition is being497 used for a given model.498 - The infrastructure currently handles internal conversion of old style499 models so that user created models in previous versions should continue500 to work for now. At some point in the future such support will go away.501 Everyone is encouraged to convert to the new structure which should be502 relatively straight forward and provides a number of benefits.503 - In that vein, the distributed models and those generated by the new504 plugin model editor are in the new format, however those generated by505 sum|multiply models are the old style sum|multiply models. This should506 also disappear in the near future507 - The on the fly discovery of plugin models and changes thereto behave508 inconsistently. If a change to a plugin model does not seem to509 register, the Load Plugin Models (under fitting -> Plugin Model510 Operations) can be used. However, after calling Load Plugin Models, the511 active plugin will no longer be loaded (even though the GUI looks like512 it is) unless it is a sum|multiply model which works properly. All513 others will need to be recalled from the model dropdown menu to reload514 the model into the calculation engine. While it might be annoying it515 does not appear to prevent SasView from working..516 - The model code and documentation review is ongoing. At this time the517 core shell parellelepiped is known to have the C shell effectively fixed518 at 0 (noted in documentation) while the triaxial ellipsoid does not seem519 to reproduce the limit of the oblate or prolate ellipsoid. If errors are520 found and corrected, corrected versions will be uploaded to the521 marketplace.522 523 428 3.1- All systems: 524 429 - The documentation window may take a few seconds to load the first time -
sasview/local_config.py
rf9d1f60 r73cbeec 33 33 ''' remember to:''' 34 34 _acknowledgement_preamble_bullet1 =\ 35 '''Acknowledge its use in your publications as :'''35 '''Acknowledge its use in your publications as suggested below;''' 36 36 _acknowledgement_preamble_bullet2 =\ 37 '''Reference SasView as:''' 37 '''Reference SasView as : M. Doucet, et al. SasView Version 4.0, Zenodo''' +\ 38 ''', http://doi.org/10.5281/zenodo.159083;''' 38 39 _acknowledgement_preamble_bullet3 =\ 39 '''Reference the model you used if appropriate (see documentation for refs) '''40 '''Reference the model you used if appropriate (see documentation for refs);''' 40 41 _acknowledgement_preamble_bullet4 =\ 41 42 '''Send us your reference for our records: developers@sasview.org''' 42 43 _acknowledgement_publications = \ 43 '''This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.'''44 _acknowledgement_citation = \ 45 '''M. Doucet et al. SasView Version 4.1, Zenodo, 10.5281/zenodo.438138'''44 '''This work benefited from the use of the SasView application, originally developed under NSF Award 45 DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme 46 under the SINE2020 project Grant No 654000, and by Patrick O'Brien & Adam Washington.''' 46 47 47 48 _acknowledgement = \ 48 '''This work was originally developed as part of the DANSE project funded by the US NSF under Award DMR-0520547,\n but is currently maintained by a collaboration between UTK, UMD, NIST, ORNL, ISIS, ESS, ILL, ANSTO and TU Delft and the scattering community.\n\n SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project (Grant No 654000).\nA list of individual contributors can be found at: https://github.com/orgs/SasView/people 49 ''' 49 '''This work was originally developed as part of the DANSE project funded by the US NSF under Award DMR-0520547, but is currently maintained 50 by a collaboration between UTK, UMD, NIST, ORNL, ISIS, ESS, ILL, ANSTO and TU Delft. SasView also contains code developed with funding from the 51 EU Horizon 2020 programme under the SINE2020 project (Grant No 654000), and by Patrick O'Brien (pycrust) and Adam Washington (corfunc-py).''' 50 52 51 53 _homepage = "http://www.sasview.org" … … 87 89 _corner_image = os.path.join(icon_path, "angles_flat.png") 88 90 _welcome_image = os.path.join(icon_path, "SVwelcome.png") 89 _copyright = "(c) 2009 - 201 7, UTK, UMD, NIST, ORNL, ISIS, ESS, ILL, ANSTO and TU Delft"91 _copyright = "(c) 2009 - 2016, UTK, UMD, NIST, ORNL, ISIS, ESS, ILL, ANSTO and TU Delft" 90 92 marketplace_url = "http://marketplace.sasview.org/" 91 93 -
setup.py
r27109e5 r18e7309 206 206 ) 207 207 208 208 209 # sas.sascalc.pr 209 210 srcdir = os.path.join("src", "sas", "sascalc", "pr", "c_extensions") … … 228 229 ) ) 229 230 230 #sas.sascalc.corfunc231 package_dir["sas.sascalc.corfunc"] = os.path.join("src", "sas", "sascalc", "corfunc")232 packages.extend(["sas.sascalc.corfunc"])233 234 231 # sas.sascalc.fit 235 232 package_dir["sas.sascalc.fit"] = os.path.join("src", "sas", "sascalc", "fit") … … 240 237 package_dir["sas.sasgui.perspectives.pr"] = os.path.join("src", "sas", "sasgui", "perspectives", "pr") 241 238 packages.extend(["sas.sasgui.perspectives","sas.sasgui.perspectives.pr"]) 242 package_data["sas.sasgui.perspectives.pr"] = [' media/*']239 package_data["sas.sasgui.perspectives.pr"] = ['images/*'] 243 240 244 241 package_dir["sas.sasgui.perspectives.invariant"] = os.path.join("src", "sas", "sasgui", "perspectives", "invariant") … … 253 250 packages.extend(["sas.sasgui.perspectives", "sas.sasgui.perspectives.calculator"]) 254 251 package_data['sas.sasgui.perspectives.calculator'] = ['images/*', 'media/*'] 255 256 package_dir["sas.sasgui.perspectives.corfunc"] = os.path.join("src", "sas", "sasgui", "perspectives", "corfunc")257 packages.extend(["sas.sasgui.perspectives.corfunc"])258 package_data['sas.sasgui.perspectives.corfunc'] = ['media/*']259 260 package_dir["sas.sasgui.perspectives.file_converter"] = os.path.join("src", "sas", "sasgui", "perspectives", "file_converter")261 packages.extend(["sas.sasgui.perspectives.file_converter"])262 package_data['sas.sasgui.perspectives.file_converter'] = ['media/*']263 252 264 253 # Data util … … 315 304 'test/1d_data/*', 316 305 'test/2d_data/*', 317 'test/convertible_files/*',318 'test/coordinate_data/*',319 'test/image_data/*',320 'test/media/*',321 'test/other_files/*',322 306 'test/save_states/*', 323 'test/ sesans_data/*'324 ]307 'test/upcoming_formats/*', 308 'default_categories.json'] 325 309 packages.append("sas.sasview") 326 310 -
src/sas/sascalc/calculator/slit_length_calculator.py
rbfba720 rb699768 16 16 # y data 17 17 self.y = None 18 # 18 #default slit length 19 19 self.slit_length = 0.0 20 20 … … 42 42 """ 43 43 # None data do nothing 44 if self.y is None or self.x isNone:44 if self.y == None or self.x == None: 45 45 return 46 46 # set local variable … … 54 54 y_sum = 0.0 55 55 y_max = 0.0 56 ind = 0 56 ind = 0.0 57 57 58 58 # sum 10 or more y values until getting max_y, … … 70 70 # defaults 71 71 y_half_d = 0.0 72 ind = 0 72 ind = 0.0 73 73 # find indices where it crosses y = y_half. 74 74 while True: … … 81 81 82 82 # y value and ind just before passed the spot of the half height 83 y_half_u = y[ind -1]83 y_half_u = y[ind-1] 84 84 85 85 # get corresponding x values 86 86 x_half_d = x[ind] 87 x_half_u = x[ind -1]87 x_half_u = x[ind-1] 88 88 89 89 # calculate x at y = y_half using linear interpolation … … 91 91 x_half = (x_half_d + x_half_u)/2.0 92 92 else: 93 x_half = ( (x_half_u * (y_half - y_half_d)94 + x_half_d * (y_half_u - y_half)) 95 / (y_half_u - y_half_d))93 x_half = (x_half_u * (y_half - y_half_d) \ 94 + x_half_d * (y_half_u - y_half)) \ 95 / (y_half_u - y_half_d) 96 96 97 97 # Our slit length is half width, so just give half beam value -
src/sas/sascalc/data_util/qsmearing.py
rc1c9929 rd3911e3 14 14 import sys 15 15 16 import numpy as np # type: ignore17 from numpy import pi, exp # type:ignore18 19 16 from sasmodels.resolution import Slit1D, Pinhole1D 20 from sasmodels.sesans import SesansTransform21 17 from sasmodels.resolution2d import Pinhole2D 22 from .nxsunit import Converter23 18 24 19 def smear_selection(data, model = None): … … 41 36 # Sanity check. If we are not dealing with a SAS Data1D 42 37 # object, just return None 43 # This checks for 2D data (does not throw exception because fail is common)44 38 if data.__class__.__name__ not in ['Data1D', 'Theory1D']: 45 39 if data == None: … … 47 41 elif data.dqx_data == None or data.dqy_data == None: 48 42 return None 49 return PySmear2D(data )50 # This checks for 1D data with smearing info in the data itself (again, fail is likely; no exceptions) 43 return PySmear2D(data, model) 44 51 45 if not hasattr(data, "dx") and not hasattr(data, "dxl")\ 52 46 and not hasattr(data, "dxw"): … … 54 48 55 49 # Look for resolution smearing data 56 # This is the code that checks for SESANS data; it looks for the file loader57 # TODO: change other sanity checks to check for file loader instead of data structure?58 _found_sesans = False59 #if data.dx is not None and data.meta_data['loader']=='SESANS':60 if data.dx is not None and data.isSesans:61 #if data.dx[0] > 0.0:62 if numpy.size(data.dx[data.dx <= 0]) == 0:63 _found_sesans = True64 # if data.dx[0] <= 0.0:65 if numpy.size(data.dx[data.dx <= 0]) > 0:66 raise ValueError('one or more of your dx values are negative, please check the data file!')67 68 if _found_sesans == True:69 #Pre-compute the Hankel matrix (H)70 qmax, qunits = data.sample.zacceptance71 SElength = Converter(data._xunit)(data.x, "A")72 zaccept = Converter(qunits)(qmax, "1/A"),73 Rmax = 1000000074 hankel = SesansTransform(data.x, SElength, zaccept, Rmax)75 # Then return the actual transform, as if it were a smearing function76 return PySmear(hankel, model, offset=0)77 78 50 _found_resolution = False 79 51 if data.dx is not None and len(data.dx) == len(data.x): … … 117 89 Wrapper for pure python sasmodels resolution functions. 118 90 """ 119 def __init__(self, resolution, model , offset=None):91 def __init__(self, resolution, model): 120 92 self.model = model 121 93 self.resolution = resolution 122 if offset is None: 123 offset = numpy.searchsorted(self.resolution.q_calc, self.resolution.q[0]) 124 self.offset = offset 94 self.offset = numpy.searchsorted(self.resolution.q_calc, self.resolution.q[0]) 125 95 126 96 def apply(self, iq_in, first_bin=0, last_bin=None): -
src/sas/sascalc/dataloader/data_info.py
r2ffe241 r345e7e4 25 25 import numpy 26 26 import math 27 28 class plottable_sesans1D(object): 29 """ 30 SESANS is a place holder for 1D SESANS plottables. 31 32 #TODO: This was directly copied from the plottables_1D. Modified Somewhat. 33 #Class has been updated. 34 """ 35 # The presence of these should be mutually 36 # exclusive with the presence of Qdev (dx) 37 x = None 38 y = None 39 lam = None 40 dx = None 41 dy = None 42 dlam = None 43 ## Slit smearing length 44 dxl = None 45 ## Slit smearing width 46 dxw = None 47 48 # Units 49 _xaxis = '' 50 _xunit = '' 51 _yaxis = '' 52 _yunit = '' 53 54 def __init__(self, x, y, lam, dx=None, dy=None, dlam=None): 55 # print "SESANS plottable working" 56 self.x = numpy.asarray(x) 57 self.y = numpy.asarray(y) 58 self.lam = numpy.asarray(lam) 59 if dx is not None: 60 self.dx = numpy.asarray(dx) 61 if dy is not None: 62 self.dy = numpy.asarray(dy) 63 if dlam is not None: 64 self.dlam = numpy.asarray(dlam) 65 66 def xaxis(self, label, unit): 67 """ 68 set the x axis label and unit 69 """ 70 self._xaxis = label 71 self._xunit = unit 72 73 def yaxis(self, label, unit): 74 """ 75 set the y axis label and unit 76 """ 77 self._yaxis = label 78 self._yunit = unit 79 27 80 28 81 class plottable_1D(object): … … 40 93 ## Slit smearing width 41 94 dxw = None 42 ## SESANS specific params (wavelengths for spin echo length calculation)43 lam = None44 dlam = None45 95 46 96 # Units … … 50 100 _yunit = '' 51 101 52 def __init__(self, x, y, dx=None, dy=None, dxl=None, dxw=None , lam=None, dlam=None):102 def __init__(self, x, y, dx=None, dy=None, dxl=None, dxw=None): 53 103 self.x = numpy.asarray(x) 54 104 self.y = numpy.asarray(y) … … 61 111 if dxw is not None: 62 112 self.dxw = numpy.asarray(dxw) 63 if lam is not None:64 self.lam = numpy.asarray(lam)65 if dlam is not None:66 self.dlam = numpy.asarray(dlam)67 113 68 114 def xaxis(self, label, unit): … … 352 398 ## Details 353 399 details = None 354 ## SESANS zacceptance355 zacceptance = None356 400 357 401 def __init__(self): … … 491 535 ## Loading errors 492 536 errors = None 493 ## SESANS data check494 isSesans = None495 496 537 497 538 def __init__(self): … … 526 567 ## Loading errors 527 568 self.errors = [] 528 ## SESANS data check529 self.isSesans = False530 569 531 570 def append_empty_process(self): … … 547 586 _str += "Title: %s\n" % self.title 548 587 _str += "Run: %s\n" % str(self.run) 549 _str += "SESANS: %s\n" % str(self.isSesans)550 588 _str += "Instrument: %s\n" % str(self.instrument) 551 589 _str += "%s\n" % str(self.sample) … … 698 736 return self._perform_union(other) 699 737 700 class Data1D(plottable_1D, DataInfo): 701 """ 702 1D data class 703 """ 704 def __init__(self, x=None, y=None, dx=None, dy=None, lam=None, dlam=None, isSesans=None): 738 class SESANSData1D(plottable_sesans1D, DataInfo): 739 """ 740 SESANS 1D data class 741 """ 742 x_unit = 'nm' 743 y_unit = 'pol' 744 745 def __init__(self, x=None, y=None, lam=None, dx=None, dy=None, dlam=None): 705 746 DataInfo.__init__(self) 706 plottable_1D.__init__(self, x, y, dx, dy,None, None, lam, dlam) 707 self.isSesans = isSesans 708 try: 709 if self.isSesans: # the data is SESANS 710 self.x_unit = 'A' 711 self.y_unit = 'pol' 712 elif not self.isSesans: # the data is SANS 713 self.x_unit = '1/A' 714 self.y_unit = '1/cm' 715 except: # the data is not recognized/supported, and the user is notified 716 raise(TypeError, 'data not recognized, check documentation for supported 1D data formats') 747 plottable_sesans1D.__init__(self, x, y, lam, dx, dy, dlam) 717 748 718 749 def __str__(self): … … 728 759 return _str 729 760 761 def clone_without_data(self, length=0, clone=None): 762 """ 763 Clone the current object, without copying the data (which 764 will be filled out by a subsequent operation). 765 The data arrays will be initialized to zero. 766 767 :param length: length of the data array to be initialized 768 :param clone: if provided, the data will be copied to clone 769 """ 770 from copy import deepcopy 771 if clone is None or not issubclass(clone.__class__, Data1D): 772 x = numpy.zeros(length) 773 dx = numpy.zeros(length) 774 y = numpy.zeros(length) 775 dy = numpy.zeros(length) 776 clone = Data1D(x, y, dx=dx, dy=dy) 777 778 clone.title = self.title 779 clone.run = self.run 780 clone.filename = self.filename 781 clone.instrument = self.instrument 782 clone.notes = deepcopy(self.notes) 783 clone.process = deepcopy(self.process) 784 clone.detector = deepcopy(self.detector) 785 clone.sample = deepcopy(self.sample) 786 clone.source = deepcopy(self.source) 787 clone.collimation = deepcopy(self.collimation) 788 clone.trans_spectrum = deepcopy(self.trans_spectrum) 789 clone.meta_data = deepcopy(self.meta_data) 790 clone.errors = deepcopy(self.errors) 791 792 return clone 793 794 class Data1D(plottable_1D, DataInfo): 795 """ 796 1D data class 797 """ 798 x_unit = '1/A' 799 y_unit = '1/cm' 800 801 def __init__(self, x, y, dx=None, dy=None): 802 DataInfo.__init__(self) 803 plottable_1D.__init__(self, x, y, dx, dy) 804 805 def __str__(self): 806 """ 807 Nice printout 808 """ 809 _str = "%s\n" % DataInfo.__str__(self) 810 _str += "Data:\n" 811 _str += " Type: %s\n" % self.__class__.__name__ 812 _str += " X-axis: %s\t[%s]\n" % (self._xaxis, self._xunit) 813 _str += " Y-axis: %s\t[%s]\n" % (self._yaxis, self._yunit) 814 _str += " Length: %g\n" % len(self.x) 815 return _str 816 730 817 def is_slit_smeared(self): 731 818 """ … … 756 843 y = numpy.zeros(length) 757 844 dy = numpy.zeros(length) 758 lam = numpy.zeros(length) 759 dlam = numpy.zeros(length) 760 clone = Data1D(x, y, lam=lam, dx=dx, dy=dy, dlam=dlam) 845 clone = Data1D(x, y, dx=dx, dy=dy) 761 846 762 847 clone.title = self.title … … 933 1018 ## Vector of Q-values at the center of each bin in y 934 1019 y_bins = None 935 ## No 2D SESANS data as of yet. Always set it to False936 isSesans = False937 1020 938 1021 def __init__(self, data=None, err_data=None, qx_data=None, 939 1022 qy_data=None, q_data=None, mask=None, 940 1023 dqx_data=None, dqy_data=None): 1024 self.y_bins = [] 1025 self.x_bins = [] 941 1026 DataInfo.__init__(self) 942 1027 plottable_2D.__init__(self, data, err_data, qx_data, 943 1028 qy_data, q_data, mask, dqx_data, dqy_data) 944 self.y_bins = []945 self.x_bins = []946 947 1029 if len(self.detector) > 0: 948 1030 raise RuntimeError, "Data2D: Detector bank already filled at init" … … 1183 1265 final_dataset.xmin = data.xmin 1184 1266 final_dataset.ymin = data.ymin 1185 final_dataset.isSesans = datainfo.isSesans1186 1267 final_dataset.title = datainfo.title 1187 1268 final_dataset.run = datainfo.run -
src/sas/sascalc/dataloader/readers/cansas_constants.py
rad4632c r250fec92 133 133 "variable" : None, 134 134 "children" : {"Idata" : SASDATA_IDATA, 135 "Sesans": {"storeas": "content"},136 "zacceptance": {"storeas": "float"},137 135 "<any>" : ANY 138 136 } -
src/sas/sascalc/dataloader/readers/cansas_reader.py
r8434365 rbcabf4e 261 261 # I and Q - 1D data 262 262 elif tagname == 'I' and isinstance(self.current_dataset, plottable_1D): 263 unit_list = unit.split("|") 264 if len(unit_list) > 1: 265 self.current_dataset.yaxis(unit_list[0].strip(), 266 unit_list[1].strip()) 267 else: 268 self.current_dataset.yaxis("Intensity", unit) 263 self.current_dataset.yaxis("Intensity", unit) 269 264 self.current_dataset.y = np.append(self.current_dataset.y, data_point) 270 265 elif tagname == 'Idev' and isinstance(self.current_dataset, plottable_1D): 271 266 self.current_dataset.dy = np.append(self.current_dataset.dy, data_point) 272 267 elif tagname == 'Q': 273 unit_list = unit.split("|") 274 if len(unit_list) > 1: 275 self.current_dataset.xaxis(unit_list[0].strip(), 276 unit_list[1].strip()) 277 else: 278 self.current_dataset.xaxis("Q", unit) 268 self.current_dataset.xaxis("Q", unit) 279 269 self.current_dataset.x = np.append(self.current_dataset.x, data_point) 280 270 elif tagname == 'Qdev': … … 288 278 elif tagname == 'Shadowfactor': 289 279 pass 290 elif tagname == 'Sesans':291 self.current_datainfo.isSesans = bool(data_point)292 elif tagname == 'zacceptance':293 self.current_datainfo.sample.zacceptance = (data_point, unit)294 280 295 281 # I and Qx, Qy - 2D data … … 930 916 self._write_data(datainfo, entry_node) 931 917 # Transmission Spectrum Info 932 # TODO: fix the writer to linearize all data, including T_spectrum 933 # self._write_trans_spectrum(datainfo, entry_node) 918 self._write_trans_spectrum(datainfo, entry_node) 934 919 # Sample info 935 920 self._write_sample_info(datainfo, entry_node) … … 1035 1020 node.append(point) 1036 1021 self.write_node(point, "Q", datainfo.x[i], 1037 {'unit': datainfo. _xaxis + " | " + datainfo._xunit})1022 {'unit': datainfo.x_unit}) 1038 1023 if len(datainfo.y) >= i: 1039 1024 self.write_node(point, "I", datainfo.y[i], 1040 {'unit': datainfo. _yaxis + " | " + datainfo._yunit})1025 {'unit': datainfo.y_unit}) 1041 1026 if datainfo.dy is not None and len(datainfo.dy) > i: 1042 1027 self.write_node(point, "Idev", datainfo.dy[i], 1043 {'unit': datainfo. _yaxis + " | " + datainfo._yunit})1028 {'unit': datainfo.y_unit}) 1044 1029 if datainfo.dx is not None and len(datainfo.dx) > i: 1045 1030 self.write_node(point, "Qdev", datainfo.dx[i], 1046 {'unit': datainfo. _xaxis + " | " + datainfo._xunit})1031 {'unit': datainfo.x_unit}) 1047 1032 if datainfo.dxw is not None and len(datainfo.dxw) > i: 1048 1033 self.write_node(point, "dQw", datainfo.dxw[i], 1049 {'unit': datainfo. _xaxis + " | " + datainfo._xunit})1034 {'unit': datainfo.x_unit}) 1050 1035 if datainfo.dxl is not None and len(datainfo.dxl) > i: 1051 1036 self.write_node(point, "dQl", datainfo.dxl[i], 1052 {'unit': datainfo._xaxis + " | " + datainfo._xunit}) 1053 if datainfo.isSesans: 1054 sesans = self.create_element("Sesans") 1055 sesans.text = str(datainfo.isSesans) 1056 node.append(sesans) 1057 self.write_node(node, "zacceptance", datainfo.sample.zacceptance[0], 1058 {'unit': datainfo.sample.zacceptance[1]}) 1059 1037 {'unit': datainfo.x_unit}) 1060 1038 1061 1039 def _write_data_2d(self, datainfo, entry_node): -
src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py
rc94280c rbbd0f37 9 9 import sys 10 10 11 from sas.sascalc.dataloader.data_info import plottable_1D, plottable_2D,\ 12 Data1D, Data2D, DataInfo, Process, Aperture, Collimation, \ 13 TransmissionSpectrum, Detector 11 from sas.sascalc.dataloader.data_info import plottable_1D, plottable_2D, Data1D, Data2D, DataInfo, Process, Aperture 12 from sas.sascalc.dataloader.data_info import Collimation, TransmissionSpectrum, Detector 14 13 from sas.sascalc.dataloader.data_info import combine_data_info_with_plottable 14 15 15 16 16 17 17 class Reader(): 18 18 """ 19 A class for reading in CanSAS v2.0 data files. The existing iteration opens 20 Mantid generated HDF5 formatted files with file extension .h5/.H5. Any 21 number of data sets may be present within the file and any dimensionality 22 of data may be used. Currently 1D and 2D SAS data sets are supported, but 23 future implementations will include 1D and 2D SESANS data. 24 25 Any number of SASdata sets may be present in a SASentry and the data within 26 can be either 1D I(Q) or 2D I(Qx, Qy). 19 A class for reading in CanSAS v2.0 data files. The existing iteration opens Mantid generated HDF5 formatted files 20 with file extension .h5/.H5. Any number of data sets may be present within the file and any dimensionality of data 21 may be used. Currently 1D and 2D SAS data sets are supported, but future implementations will include 1D and 2D 22 SESANS data. 23 24 Any number of SASdata sets may be present in a SASentry and the data within can be either 1D I(Q) or 2D I(Qx, Qy). 27 25 28 26 Also supports reading NXcanSAS formatted HDF5 files … … 32 30 """ 33 31 34 # CanSAS version32 ## CanSAS version 35 33 cansas_version = 2.0 36 # Logged warnings or messages34 ## Logged warnings or messages 37 35 logging = None 38 # List of errors for the current data set36 ## List of errors for the current data set 39 37 errors = None 40 # Raw file contents to be processed38 ## Raw file contents to be processed 41 39 raw_data = None 42 # Data info currently being read in40 ## Data info currently being read in 43 41 current_datainfo = None 44 # SASdata set currently being read in42 ## SASdata set currently being read in 45 43 current_dataset = None 46 # List of plottable1D objects that should be linked to the current_datainfo44 ## List of plottable1D objects that should be linked to the current_datainfo 47 45 data1d = None 48 # List of plottable2D objects that should be linked to the current_datainfo46 ## List of plottable2D objects that should be linked to the current_datainfo 49 47 data2d = None 50 # Data type name48 ## Data type name 51 49 type_name = "CanSAS 2.0" 52 # Wildcards50 ## Wildcards 53 51 type = ["CanSAS 2.0 HDF5 Files (*.h5)|*.h5"] 54 # List of allowed extensions52 ## List of allowed extensions 55 53 ext = ['.h5', '.H5'] 56 # Flag to bypass extension check57 allow_all = True58 # List of files to return54 ## Flag to bypass extension check 55 allow_all = False 56 ## List of files to return 59 57 output = None 60 58 … … 66 64 :return: List of Data1D/2D objects and/or a list of errors. 67 65 """ 68 # Reinitializewhen loading a new data file to reset all class variables66 ## Reinitialize the class when loading a new data file to reset all class variables 69 67 self.reset_class_variables() 70 # Check that the file exists68 ## Check that the file exists 71 69 if os.path.isfile(filename): 72 70 basename = os.path.basename(filename) … … 74 72 # If the file type is not allowed, return empty list 75 73 if extension in self.ext or self.allow_all: 76 # Load the data file74 ## Load the data file 77 75 self.raw_data = h5py.File(filename, 'r') 78 # Read in all child elements of top level SASroot76 ## Read in all child elements of top level SASroot 79 77 self.read_children(self.raw_data, []) 80 # Add the last data set to the list of outputs78 ## Add the last data set to the list of outputs 81 79 self.add_data_set() 82 # Close the data file80 ## Close the data file 83 81 self.raw_data.close() 84 # Return data set(s)82 ## Return data set(s) 85 83 return self.output 86 84 … … 112 110 """ 113 111 114 # Loop through each element of the parent and process accordingly112 ## Loop through each element of the parent and process accordingly 115 113 for key in data.keys(): 116 # Get all information for the current key114 ## Get all information for the current key 117 115 value = data.get(key) 118 116 if value.attrs.get(u'canSAS_class') is not None: … … 128 126 self.parent_class = class_name 129 127 parent_list.append(key) 130 # If a new sasentry, store the current data sets and create 131 # a fresh Data1D/2D object 128 ## If this is a new sasentry, store the current data sets and create a fresh Data1D/2D object 132 129 if class_prog.match(u'SASentry'): 133 130 self.add_data_set(key) 134 131 elif class_prog.match(u'SASdata'): 135 132 self._initialize_new_data_set(parent_list) 136 # Recursion step to access data within the group133 ## Recursion step to access data within the group 137 134 self.read_children(value, parent_list) 138 135 self.add_intermediate() … … 140 137 141 138 elif isinstance(value, h5py.Dataset): 142 # If this is a dataset, store the data appropriately139 ## If this is a dataset, store the data appropriately 143 140 data_set = data[key][:] 144 141 unit = self._get_unit(value) 145 142 146 # I and Q Data143 ## I and Q Data 147 144 if key == u'I': 148 if isinstance(self.current_dataset, plottable_2D):145 if type(self.current_dataset) is plottable_2D: 149 146 self.current_dataset.data = data_set 150 147 self.current_dataset.zaxis("Intensity", unit) … … 154 151 continue 155 152 elif key == u'Idev': 156 if isinstance(self.current_dataset, plottable_2D):153 if type(self.current_dataset) is plottable_2D: 157 154 self.current_dataset.err_data = data_set.flatten() 158 155 else: … … 161 158 elif key == u'Q': 162 159 self.current_dataset.xaxis("Q", unit) 163 if isinstance(self.current_dataset, plottable_2D):160 if type(self.current_dataset) is plottable_2D: 164 161 self.current_dataset.q = data_set.flatten() 165 162 else: … … 169 166 self.current_dataset.dx = data_set.flatten() 170 167 continue 171 elif key == u'dQw':172 self.current_dataset.dxw = data_set.flatten()173 continue174 elif key == u'dQl':175 self.current_dataset.dxl = data_set.flatten()176 continue177 168 elif key == u'Qy': 178 169 self.current_dataset.yaxis("Q_y", unit) … … 192 183 self.current_dataset.mask = data_set.flatten() 193 184 continue 194 # Transmission Spectrum195 elif (key == u'T'196 and self.parent_class == u'SAStransmission_spectrum'):197 self.trans_spectrum.transmission = data_set.flatten()198 continue199 elif (key == u'Tdev'200 and self.parent_class == u'SAStransmission_spectrum'):201 self.trans_spectrum.transmission_deviation = \202 data_set.flatten()203 continue204 elif (key == u'lambda'205 and self.parent_class == u'SAStransmission_spectrum'):206 self.trans_spectrum.wavelength = data_set.flatten()207 continue208 185 209 186 for data_point in data_set: 210 # Top Level Meta Data187 ## Top Level Meta Data 211 188 if key == u'definition': 212 189 self.current_datainfo.meta_data['reader'] = data_point … … 224 201 self.current_datainfo.notes.append(data_point) 225 202 226 # Sample Information 227 # CanSAS 2.0 format 228 elif key == u'Title' and self.parent_class == u'SASsample': 203 ## Sample Information 204 elif key == u'Title' and self.parent_class == u'SASsample': # CanSAS 2.0 format 229 205 self.current_datainfo.sample.name = data_point 230 # NXcanSAS format 231 elif key == u'name' and self.parent_class == u'SASsample': 206 elif key == u'ID' and self.parent_class == u'SASsample': # NXcanSAS format 232 207 self.current_datainfo.sample.name = data_point 233 # NXcanSAS format 234 elif key == u'ID' and self.parent_class == u'SASsample': 235 self.current_datainfo.sample.name = data_point 236 elif (key == u'thickness' 237 and self.parent_class == u'SASsample'): 208 elif key == u'thickness' and self.parent_class == u'SASsample': 238 209 self.current_datainfo.sample.thickness = data_point 239 elif (key == u'temperature' 240 and self.parent_class == u'SASsample'): 210 elif key == u'temperature' and self.parent_class == u'SASsample': 241 211 self.current_datainfo.sample.temperature = data_point 242 elif (key == u'transmission' 243 and self.parent_class == u'SASsample'): 212 elif key == u'transmission' and self.parent_class == u'SASsample': 244 213 self.current_datainfo.sample.transmission = data_point 245 elif (key == u'x_position' 246 and self.parent_class == u'SASsample'): 214 elif key == u'x_position' and self.parent_class == u'SASsample': 247 215 self.current_datainfo.sample.position.x = data_point 248 elif (key == u'y_position' 249 and self.parent_class == u'SASsample'): 216 elif key == u'y_position' and self.parent_class == u'SASsample': 250 217 self.current_datainfo.sample.position.y = data_point 251 elif key == u'p itch' and self.parent_class == u'SASsample':218 elif key == u'polar_angle' and self.parent_class == u'SASsample': 252 219 self.current_datainfo.sample.orientation.x = data_point 253 elif key == u'yaw' and self.parent_class == u'SASsample': 254 self.current_datainfo.sample.orientation.y = data_point 255 elif key == u'roll' and self.parent_class == u'SASsample': 220 elif key == u'azimuthal_angle' and self.parent_class == u'SASsample': 256 221 self.current_datainfo.sample.orientation.z = data_point 257 elif (key == u'details' 258 and self.parent_class == u'SASsample'): 222 elif key == u'details' and self.parent_class == u'SASsample': 259 223 self.current_datainfo.sample.details.append(data_point) 260 224 261 # Instrumental Information 262 elif (key == u'name' 263 and self.parent_class == u'SASinstrument'): 225 ## Instrumental Information 226 elif key == u'name' and self.parent_class == u'SASinstrument': 264 227 self.current_datainfo.instrument = data_point 265 228 elif key == u'name' and self.parent_class == u'SASdetector': … … 268 231 self.detector.distance = float(data_point) 269 232 self.detector.distance_unit = unit 270 elif (key == u'slit_length' 271 and self.parent_class == u'SASdetector'): 233 elif key == u'slit_length' and self.parent_class == u'SASdetector': 272 234 self.detector.slit_length = float(data_point) 273 235 self.detector.slit_length_unit = unit 274 elif (key == u'x_position' 275 and self.parent_class == u'SASdetector'): 236 elif key == u'x_position' and self.parent_class == u'SASdetector': 276 237 self.detector.offset.x = float(data_point) 277 238 self.detector.offset_unit = unit 278 elif (key == u'y_position' 279 and self.parent_class == u'SASdetector'): 239 elif key == u'y_position' and self.parent_class == u'SASdetector': 280 240 self.detector.offset.y = float(data_point) 281 241 self.detector.offset_unit = unit 282 elif (key == u'pitch' 283 and self.parent_class == u'SASdetector'): 242 elif key == u'polar_angle' and self.parent_class == u'SASdetector': 284 243 self.detector.orientation.x = float(data_point) 285 244 self.detector.orientation_unit = unit 286 elif key == u' roll' and self.parent_class == u'SASdetector':245 elif key == u'azimuthal_angle' and self.parent_class == u'SASdetector': 287 246 self.detector.orientation.z = float(data_point) 288 247 self.detector.orientation_unit = unit 289 elif key == u'yaw' and self.parent_class == u'SASdetector': 290 self.detector.orientation.y = float(data_point) 291 self.detector.orientation_unit = unit 292 elif (key == u'beam_center_x' 293 and self.parent_class == u'SASdetector'): 248 elif key == u'beam_center_x' and self.parent_class == u'SASdetector': 294 249 self.detector.beam_center.x = float(data_point) 295 250 self.detector.beam_center_unit = unit 296 elif (key == u'beam_center_y' 297 and self.parent_class == u'SASdetector'): 251 elif key == u'beam_center_y' and self.parent_class == u'SASdetector': 298 252 self.detector.beam_center.y = float(data_point) 299 253 self.detector.beam_center_unit = unit 300 elif (key == u'x_pixel_size' 301 and self.parent_class == u'SASdetector'): 254 elif key == u'x_pixel_size' and self.parent_class == u'SASdetector': 302 255 self.detector.pixel_size.x = float(data_point) 303 256 self.detector.pixel_size_unit = unit 304 elif (key == u'y_pixel_size' 305 and self.parent_class == u'SASdetector'): 257 elif key == u'y_pixel_size' and self.parent_class == u'SASdetector': 306 258 self.detector.pixel_size.y = float(data_point) 307 259 self.detector.pixel_size_unit = unit 308 elif (key == u'distance' 309 and self.parent_class == u'SAScollimation'): 260 elif key == u'SSD' and self.parent_class == u'SAScollimation': 310 261 self.collimation.length = data_point 311 262 self.collimation.length_unit = unit 312 elif (key == u'name' 313 and self.parent_class == u'SAScollimation'): 263 elif key == u'name' and self.parent_class == u'SAScollimation': 314 264 self.collimation.name = data_point 315 elif (key == u'shape' 316 and self.parent_class == u'SASaperture'): 317 self.aperture.shape = data_point 318 elif (key == u'x_gap' 319 and self.parent_class == u'SASaperture'): 320 self.aperture.size.x = data_point 321 elif (key == u'y_gap' 322 and self.parent_class == u'SASaperture'): 323 self.aperture.size.y = data_point 324 325 # Process Information 326 elif (key == u'Title' 327 and self.parent_class == u'SASprocess'): # CanSAS 2.0 265 266 ## Process Information 267 elif key == u'name' and self.parent_class == u'SASprocess': 328 268 self.process.name = data_point 329 elif (key == u'name' 330 and self.parent_class == u'SASprocess'): # NXcanSAS 269 elif key == u'Title' and self.parent_class == u'SASprocess': # CanSAS 2.0 format 331 270 self.process.name = data_point 332 elif (key == u'description' 333 and self.parent_class == u'SASprocess'): 271 elif key == u'name' and self.parent_class == u'SASprocess': # NXcanSAS format 272 self.process.name = data_point 273 elif key == u'description' and self.parent_class == u'SASprocess': 334 274 self.process.description = data_point 335 275 elif key == u'date' and self.parent_class == u'SASprocess': 336 276 self.process.date = data_point 337 elif key == u'term' and self.parent_class == u'SASprocess':338 self.process.term = data_point339 277 elif self.parent_class == u'SASprocess': 340 278 self.process.notes.append(data_point) 341 279 342 # Source 343 elif (key == u'wavelength' 344 and self.parent_class == u'SASdata'): 280 ## Transmission Spectrum 281 elif key == u'T' and self.parent_class == u'SAStransmission_spectrum': 282 self.trans_spectrum.transmission.append(data_point) 283 elif key == u'Tdev' and self.parent_class == u'SAStransmission_spectrum': 284 self.trans_spectrum.transmission_deviation.append(data_point) 285 elif key == u'lambda' and self.parent_class == u'SAStransmission_spectrum': 286 self.trans_spectrum.wavelength.append(data_point) 287 288 ## Source 289 elif key == u'wavelength' and self.parent_class == u'SASdata': 345 290 self.current_datainfo.source.wavelength = data_point 346 291 self.current_datainfo.source.wavelength_unit = unit 347 elif (key == u'incident_wavelength' 348 and self.parent_class == 'SASsource'): 292 elif key == u'incident_wavelength' and self.parent_class == u'SASsource': 349 293 self.current_datainfo.source.wavelength = data_point 350 294 self.current_datainfo.source.wavelength_unit = unit 351 elif (key == u'wavelength_max' 352 and self.parent_class == u'SASsource'): 295 elif key == u'wavelength_max' and self.parent_class == u'SASsource': 353 296 self.current_datainfo.source.wavelength_max = data_point 354 297 self.current_datainfo.source.wavelength_max_unit = unit 355 elif (key == u'wavelength_min' 356 and self.parent_class == u'SASsource'): 298 elif key == u'wavelength_min' and self.parent_class == u'SASsource': 357 299 self.current_datainfo.source.wavelength_min = data_point 358 300 self.current_datainfo.source.wavelength_min_unit = unit 359 elif (key == u'incident_wavelength_spread' 360 and self.parent_class == u'SASsource'): 361 self.current_datainfo.source.wavelength_spread = \ 362 data_point 363 self.current_datainfo.source.wavelength_spread_unit = \ 364 unit 365 elif (key == u'beam_size_x' 366 and self.parent_class == u'SASsource'): 301 elif key == u'wavelength_spread' and self.parent_class == u'SASsource': 302 self.current_datainfo.source.wavelength_spread = data_point 303 self.current_datainfo.source.wavelength_spread_unit = unit 304 elif key == u'beam_size_x' and self.parent_class == u'SASsource': 367 305 self.current_datainfo.source.beam_size.x = data_point 368 306 self.current_datainfo.source.beam_size_unit = unit 369 elif (key == u'beam_size_y' 370 and self.parent_class == u'SASsource'): 307 elif key == u'beam_size_y' and self.parent_class == u'SASsource': 371 308 self.current_datainfo.source.beam_size.y = data_point 372 309 self.current_datainfo.source.beam_size_unit = unit 373 elif (key == u'beam_shape' 374 and self.parent_class == u'SASsource'): 310 elif key == u'beam_shape' and self.parent_class == u'SASsource': 375 311 self.current_datainfo.source.beam_shape = data_point 376 elif (key == u'radiation' 377 and self.parent_class == u'SASsource'): 312 elif key == u'radiation' and self.parent_class == u'SASsource': 378 313 self.current_datainfo.source.radiation = data_point 379 elif (key == u'transmission' 380 and self.parent_class == u'SASdata'): 314 elif key == u'transmission' and self.parent_class == u'SASdata': 381 315 self.current_datainfo.sample.transmission = data_point 382 316 383 # Everything else goes in meta_data317 ## Everything else goes in meta_data 384 318 else: 385 new_key = self._create_unique_key( 386 self.current_datainfo.meta_data, key) 319 new_key = self._create_unique_key(self.current_datainfo.meta_data, key) 387 320 self.current_datainfo.meta_data[new_key] = data_point 388 321 389 322 else: 390 # I don't know if this reachable code323 ## I don't know if this reachable code 391 324 self.errors.add("ShouldNeverHappenException") 392 325 393 326 def add_intermediate(self): 394 327 """ 395 This method stores any intermediate objects within the final data set 396 after fully reading the set. 397 398 :param parent: The NXclass name for the h5py Group object that just 399 finished being processed 328 This method stores any intermediate objects within the final data set after fully reading the set. 329 330 :param parent: The NXclass name for the h5py Group object that just finished being processed 400 331 """ 401 332 … … 416 347 self.aperture = Aperture() 417 348 elif self.parent_class == u'SASdata': 418 if isinstance(self.current_dataset, plottable_2D):349 if type(self.current_dataset) is plottable_2D: 419 350 self.data2d.append(self.current_dataset) 420 elif isinstance(self.current_dataset, plottable_1D):351 elif type(self.current_dataset) is plottable_1D: 421 352 self.data1d.append(self.current_dataset) 422 353 423 354 def final_data_cleanup(self): 424 355 """ 425 Does some final cleanup and formatting on self.current_datainfo and 426 all data1D and data2D objects and then combines the data and info into 427 Data1D and Data2D objects 428 """ 429 430 # Type cast data arrays to float64 356 Does some final cleanup and formatting on self.current_datainfo and all data1D and data2D objects and then 357 combines the data and info into Data1D and Data2D objects 358 """ 359 360 ## Type cast data arrays to float64 431 361 if len(self.current_datainfo.trans_spectrum) > 0: 432 362 spectrum_list = [] … … 434 364 spectrum.transmission = np.delete(spectrum.transmission, [0]) 435 365 spectrum.transmission = spectrum.transmission.astype(np.float64) 436 spectrum.transmission_deviation = np.delete( 437 spectrum.transmission_deviation, [0]) 438 spectrum.transmission_deviation = \ 439 spectrum.transmission_deviation.astype(np.float64) 366 spectrum.transmission_deviation = np.delete(spectrum.transmission_deviation, [0]) 367 spectrum.transmission_deviation = spectrum.transmission_deviation.astype(np.float64) 440 368 spectrum.wavelength = np.delete(spectrum.wavelength, [0]) 441 369 spectrum.wavelength = spectrum.wavelength.astype(np.float64) … … 444 372 self.current_datainfo.trans_spectrum = spectrum_list 445 373 446 # Append errors to dataset and reset class errors374 ## Append errors to dataset and reset class errors 447 375 self.current_datainfo.errors = self.errors 448 376 self.errors.clear() 449 377 450 # Combine all plottables with datainfo and append each to output451 # Type cast data arrays to float64 and find min/max as appropriate378 ## Combine all plottables with datainfo and append each to output 379 ## Type cast data arrays to float64 and find min/max as appropriate 452 380 for dataset in self.data2d: 453 381 dataset.data = dataset.data.astype(np.float64) … … 469 397 zeros = np.ones(dataset.data.size, dtype=bool) 470 398 try: 471 for i in range (0, dataset.mask.size - 1):399 for i in range (0, dataset.mask.size - 1): 472 400 zeros[i] = dataset.mask[i] 473 401 except: 474 402 self.errors.add(sys.exc_value) 475 403 dataset.mask = zeros 476 # Calculate the actual Q matrix404 ## Calculate the actual Q matrix 477 405 try: 478 406 if dataset.q_data.size <= 1: 479 dataset.q_data = np.sqrt(dataset.qx_data 480 * dataset.qx_data 481 + dataset.qy_data 482 * dataset.qy_data) 407 dataset.q_data = np.sqrt(dataset.qx_data * dataset.qx_data + dataset.qy_data * dataset.qy_data) 483 408 except: 484 409 dataset.q_data = None … … 490 415 dataset.data = dataset.data.flatten() 491 416 492 final_dataset = combine_data_info_with_plottable( 493 dataset, self.current_datainfo) 417 final_dataset = combine_data_info_with_plottable(dataset, self.current_datainfo) 494 418 self.output.append(final_dataset) 495 419 … … 511 435 if dataset.dy is not None: 512 436 dataset.dy = dataset.dy.astype(np.float64) 513 final_dataset = combine_data_info_with_plottable( 514 dataset, self.current_datainfo) 437 final_dataset = combine_data_info_with_plottable(dataset, self.current_datainfo) 515 438 self.output.append(final_dataset) 516 439 517 440 def add_data_set(self, key=""): 518 441 """ 519 Adds the current_dataset to the list of outputs after preforming final 520 processing on the data and then calls a private method to generate a 521 new data set. 442 Adds the current_dataset to the list of outputs after preforming final processing on the data and then calls a 443 private method to generate a new data set. 522 444 523 445 :param key: NeXus group name for current tree level … … 531 453 532 454 533 def _initialize_new_data_set(self, parent_list=None): 534 """ 535 A private class method to generate a new 1D or 2D data object based on 536 the type of data within the set. Outside methods should call 537 add_data_set() to be sure any existing data is stored properly. 455 def _initialize_new_data_set(self, parent_list = None): 456 """ 457 A private class method to generate a new 1D or 2D data object based on the type of data within the set. 458 Outside methods should call add_data_set() to be sure any existing data is stored properly. 538 459 539 460 :param parent_list: List of names of parent elements … … 552 473 def _find_intermediate(self, parent_list, basename=""): 553 474 """ 554 A private class used to find an entry by either using a direct key or 555 knowing the approximate basename. 556 557 :param parent_list: List of parents nodes in the HDF5 file 475 A private class used to find an entry by either using a direct key or knowing the approximate basename. 476 477 :param parent_list: List of parents to the current level in the HDF5 file 558 478 :param basename: Approximate name of an entry to search for 559 479 :return: … … 566 486 top = top.get(parent) 567 487 for key in top.keys(): 568 if key_prog.match(key):488 if (key_prog.match(key)): 569 489 entry = True 570 490 break … … 596 516 """ 597 517 unit = value.attrs.get(u'units') 598 if unit isNone:518 if unit == None: 599 519 unit = value.attrs.get(u'unit') 600 # Convert the unit formats520 ## Convert the unit formats 601 521 if unit == "1/A": 602 522 unit = "A^{-1}" -
src/sas/sascalc/dataloader/readers/sesans_reader.py
r9525358 r345e7e4 8 8 import numpy 9 9 import os 10 from sas.sascalc.dataloader.data_info import Data1D10 from sas.sascalc.dataloader.data_info import SESANSData1D 11 11 12 12 # Check whether we have a converter available … … 59 59 raise RuntimeError, "sesans_reader: cannot open %s" % path 60 60 buff = input_f.read() 61 # print buff 61 62 lines = buff.splitlines() 63 # print lines 64 #Jae could not find python universal line spliter: 65 #keep the below for now 66 # some ascii data has \r line separator, 67 # try it when the data is on only one long line 68 # if len(lines) < 2 : 69 # lines = buff.split('\r') 70 62 71 x = numpy.zeros(0) 63 72 y = numpy.zeros(0) … … 74 83 tdlam = numpy.zeros(0) 75 84 tdx = numpy.zeros(0) 76 output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, isSesans=True) 85 # print "all good" 86 output = SESANSData1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam) 87 # print output 77 88 self.filename = output.filename = basename 78 89 90 # #Initialize counters for data lines and header lines. 91 # is_data = False # Has more than 5 lines 92 # # More than "5" lines of data is considered as actual 93 # # data unless that is the only data 94 # mum_data_lines = 5 95 # # To count # of current data candidate lines 96 # i = -1 97 # # To count total # of previous data candidate lines 98 # i1 = -1 99 # # To count # of header lines 100 # j = -1 101 # # Helps to count # of header lines 102 # j1 = -1 103 # #minimum required number of columns of data; ( <= 4). 104 # lentoks = 2 79 105 paramnames=[] 80 106 paramvals=[] … … 85 111 Pvals=[] 86 112 dPvals=[] 87 113 # print x 114 # print zvals 88 115 for line in lines: 89 116 # Initial try for CSV (split on ,) … … 95 122 if len(toks)>5: 96 123 zvals.append(toks[0]) 97 dzvals.append(toks[ 3])98 lamvals.append(toks[ 4])99 dlamvals.append(toks[ 5])100 Pvals.append(toks[ 1])101 dPvals.append(toks[ 2])124 dzvals.append(toks[1]) 125 lamvals.append(toks[2]) 126 dlamvals.append(toks[3]) 127 Pvals.append(toks[4]) 128 dPvals.append(toks[5]) 102 129 else: 103 130 continue … … 113 140 default_z_unit = "A" 114 141 data_conv_P = None 115 default_p_unit = " " # Adjust unit for axis (L^-3)142 default_p_unit = " " 116 143 lam_unit = lam_header[1].replace("[","").replace("]","") 117 if lam_unit == 'AA':118 lam_unit = 'A'119 144 varheader=[zvals[0],dzvals[0],lamvals[0],dlamvals[0],Pvals[0],dPvals[0]] 120 145 valrange=range(1, len(zvals)) … … 136 161 output.x, output.x_unit = self._unit_conversion(x, lam_unit, default_z_unit) 137 162 output.y = y 138 output.y_unit = r'\AA^{-2} cm^{-1}' # output y_unit added139 163 output.dx, output.dx_unit = self._unit_conversion(dx, lam_unit, default_z_unit) 140 164 output.dy = dy 141 165 output.lam, output.lam_unit = self._unit_conversion(lam, lam_unit, default_z_unit) 142 166 output.dlam, output.dlam_unit = self._unit_conversion(dlam, lam_unit, default_z_unit) 143 144 output.xaxis(r"\rm{z}", output.x_unit)145 output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", output.y_unit) # Adjust label to ln P/(lam^2 t), remove lam column refs146 167 168 output.xaxis("\rm{z}", output.x_unit) 169 output.yaxis("\\rm{P/P0}", output.y_unit) 147 170 # Store loading process information 148 171 output.meta_data['loader'] = self.type_name 149 #output.sample.thickness = float(paramvals[6])172 output.sample.thickness = float(paramvals[6]) 150 173 output.sample.name = paramvals[1] 151 174 output.sample.ID = paramvals[0] 152 175 zaccept_unit_split = paramnames[7].split("[") 153 176 zaccept_unit = zaccept_unit_split[1].replace("]","") 154 if zaccept_unit.strip() == r'\AA^-1' or zaccept_unit.strip() == r'\A^-1':177 if zaccept_unit.strip() == '\AA^-1': 155 178 zaccept_unit = "1/A" 156 179 output.sample.zacceptance=(float(paramvals[7]),zaccept_unit) 157 output.vars =varheader180 output.vars=varheader 158 181 159 182 if len(output.x) < 1: -
src/sas/sascalc/fit/AbstractFitEngine.py
ra9f579c rd3911e3 131 131 a way to get residuals from data. 132 132 """ 133 def __init__(self, x, y, dx=None, dy=None, smearer=None, data=None , lam=None, dlam=None):133 def __init__(self, x, y, dx=None, dy=None, smearer=None, data=None): 134 134 """ 135 135 :param smearer: is an object of class QSmearer or SlitSmearer … … 152 152 153 153 """ 154 Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy , lam=lam, dlam=dlam)154 Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy) 155 155 self.num_points = len(x) 156 156 self.sas_data = data -
src/sas/sascalc/fit/BumpsFitting.py
r1a30720 r345e7e4 352 352 except Exception as exc: 353 353 best, fbest = None, numpy.NaN 354 errors = [str(exc), traceback. format_exc()]354 errors = [str(exc), traceback.traceback.format_exc()] 355 355 finally: 356 356 mapper.stop_mapper(fitdriver.mapper) -
src/sas/sasgui/guiframe/CategoryInstaller.py
rddbac66 r212bfc2 123 123 compile it and install 124 124 :param homefile: Override the default home directory 125 :param model_list: List of model names except those in Plugin Models 126 which are user supplied. 125 :param model_list: List of model names except customized models 127 126 """ 128 127 _model_dict = { model.name: model for model in model_list} -
src/sas/sasgui/guiframe/acknowledgebox.py
r74c8cd0 rc1fdf84 11 11 import wx.richtext 12 12 import wx.lib.hyperlink 13 from wx.lib.expando import ExpandoTextCtrl14 13 import random 15 14 import os.path … … 37 36 Shows the current method for acknowledging SasView in 38 37 scholarly publications. 38 39 39 """ 40 40 … … 44 44 wx.Dialog.__init__(self, *args, **kwds) 45 45 46 self.ack = ExpandoTextCtrl(self, style=wx.TE_LEFT|wx.TE_MULTILINE|wx.TE_BESTWRAP|wx.TE_READONLY|wx.TE_NO_VSCROLL)46 self.ack = wx.TextCtrl(self, style=wx.TE_LEFT|wx.TE_MULTILINE|wx.TE_BESTWRAP|wx.TE_READONLY|wx.TE_NO_VSCROLL) 47 47 self.ack.SetValue(config._acknowledgement_publications) 48 #self.ack.SetMinSize((-1, 55)) 49 self.citation = ExpandoTextCtrl(self, style=wx.TE_LEFT|wx.TE_MULTILINE|wx.TE_BESTWRAP|wx.TE_READONLY|wx.TE_NO_VSCROLL) 50 self.citation.SetValue(config._acknowledgement_citation) 48 self.ack.SetMinSize((-1, 55)) 51 49 self.preamble = wx.StaticText(self, -1, config._acknowledgement_preamble) 52 50 items = [config._acknowledgement_preamble_bullet1, … … 54 52 config._acknowledgement_preamble_bullet3, 55 53 config._acknowledgement_preamble_bullet4] 56 self.list1 = wx.StaticText(self, -1, " (1) " + items[0])57 self.list2 = wx.StaticText(self, -1, " (2) " + items[1])58 self.list3 = wx.StaticText(self, -1, " (3) " + items[2])59 self.list4 = wx.StaticText(self, -1, " (4) " + items[3])54 self.list1 = wx.StaticText(self, -1, "\t(1) " + items[0]) 55 self.list2 = wx.StaticText(self, -1, "\t(2) " + items[1]) 56 self.list3 = wx.StaticText(self, -1, "\t(3) " + items[2]) 57 self.list4 = wx.StaticText(self, -1, "\t(4) " + items[3]) 60 58 self.static_line = wx.StaticLine(self, 0) 61 59 self.__set_properties() … … 71 69 self.SetTitle("Acknowledging SasView") 72 70 #Increased size of box from (525, 225), SMK, 04/10/16 73 self.Set ClientSize((600, 320))71 self.SetSize((600, 300)) 74 72 # end wxGlade 75 73 … … 83 81 sizer_titles.Add(self.preamble, 0, wx.ALL|wx.EXPAND, 5) 84 82 sizer_titles.Add(self.list1, 0, wx.ALL|wx.EXPAND, 5) 83 sizer_titles.Add(self.list2, 0, wx.ALL|wx.EXPAND, 5) 84 sizer_titles.Add(self.list3, 0, wx.ALL|wx.EXPAND, 5) 85 sizer_titles.Add(self.list4, 0, wx.ALL|wx.EXPAND, 5) 86 sizer_titles.Add(self.static_line, 0, wx.ALL|wx.EXPAND, 0) 85 87 sizer_titles.Add(self.ack, 0, wx.ALL|wx.EXPAND, 5) 86 sizer_titles.Add(self.list2, 0, wx.ALL|wx.EXPAND, 5)87 sizer_titles.Add(self.citation, 0, wx.ALL|wx.EXPAND, 5)88 sizer_titles.Add(self.list3, 0, wx.ALL|wx.EXPAND, 5)89 #sizer_titles.Add(self.static_line, 0, wx.ALL|wx.EXPAND, 0)90 sizer_titles.Add(self.list4, 0, wx.ALL|wx.EXPAND, 5)91 88 sizer_main.Add(sizer_titles, -1, wx.ALL|wx.EXPAND, 5) 92 89 self.SetAutoLayout(True) … … 94 91 self.Layout() 95 92 self.Centre() 96 #self.SetClientSize(sizer_main.GetSize())97 93 # end wxGlade 98 94 -
src/sas/sasgui/guiframe/config.py
rf9d1f60 rd85c194 1 1 """ 2 2 Application settings 3 3 """ 4 import os 4 5 import time 5 import os6 6 from sas.sasgui.guiframe.gui_style import GUIFRAME 7 import sas.sasview8 import logging9 10 7 # Version of the application 11 __appname__ = " SasView"12 __version__ = sas.sasview.__version__13 __build__ = sas.sasview.__build__8 __appname__ = "DummyView" 9 __version__ = '0.0.0' 10 __build__ = '1' 14 11 __download_page__ = 'https://github.com/SasView/sasview/releases' 15 12 __update_URL__ = 'http://www.sasview.org/latestversion.json' 16 13 14 17 15 # Debug message flag 18 __EVT_DEBUG__ = False16 __EVT_DEBUG__ = True 19 17 20 18 # Flag for automated testing … … 31 29 _acknowledgement_preamble =\ 32 30 '''To ensure the long term support and development of this software please''' +\ 33 ''' remember to :'''31 ''' remember to do the following.''' 34 32 _acknowledgement_preamble_bullet1 =\ 35 '''Acknowledge its use in your publications as :'''33 '''Acknowledge its use in your publications as suggested below''' 36 34 _acknowledgement_preamble_bullet2 =\ 37 '''Reference SasView as:'''35 '''Reference the following website: http://www.sasview.org''' 38 36 _acknowledgement_preamble_bullet3 =\ 39 37 '''Reference the model you used if appropriate (see documentation for refs)''' … … 41 39 '''Send us your reference for our records: developers@sasview.org''' 42 40 _acknowledgement_publications = \ 43 '''This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.''' 44 _acknowledgement_citation = \ 45 '''M. Doucet et al. SasView Version 4.1, Zenodo, 10.5281/zenodo.438138''' 41 '''This work benefited from the use of the SasView application, originally 42 developed under NSF award DMR-0520547. 43 ''' 44 _acknowledgement = \ 45 '''This work originally developed as part of the DANSE project funded by the NSF 46 under grant DMR-0520547, and currently maintained by NIST, UMD, ORNL, ISIS, ESS 47 and ILL. 46 48 47 _acknowledgement = \48 '''This work was originally developed as part of the DANSE project funded by the US NSF under Award DMR-0520547,\n but is currently maintained by a collaboration between UTK, UMD, NIST, ORNL, ISIS, ESS, ILL, ANSTO and TU Delft and the scattering community.\n\n SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project (Grant No 654000).\nA list of individual contributors can be found at: https://github.com/orgs/SasView/people49 49 ''' 50 51 50 _homepage = "http://www.sasview.org" 52 _download = __download_page__51 _download = "http://sourceforge.net/projects/sasview/files/" 53 52 _authors = [] 54 53 _paper = "http://sourceforge.net/p/sasview/tickets/" 55 54 _license = "mailto:help@sasview.org" 56 57 58 icon_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "images")) 59 logging.info("icon path: %s" % icon_path) 60 media_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "media")) 61 test_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "test")) 62 63 _nist_logo = os.path.join(icon_path, "nist_logo.png") 64 _umd_logo = os.path.join(icon_path, "umd_logo.png") 65 _sns_logo = os.path.join(icon_path, "sns_logo.png") 66 _ornl_logo = os.path.join(icon_path, "ornl_logo.png") 67 _isis_logo = os.path.join(icon_path, "isis_logo.png") 68 _ess_logo = os.path.join(icon_path, "ess_logo.png") 69 _ill_logo = os.path.join(icon_path, "ill_logo.png") 70 _ansto_logo = os.path.join(icon_path, "ansto_logo.png") 71 _tudelft_logo = os.path.join(icon_path, "tudelft_logo.png") 72 _nsf_logo = os.path.join(icon_path, "nsf_logo.png") 73 _danse_logo = os.path.join(icon_path, "danse_logo.png") 74 _inst_logo = os.path.join(icon_path, "utlogo.gif") 55 _nsf_logo = "images/nsf_logo.png" 56 _danse_logo = "images/danse_logo.png" 57 _inst_logo = "images/utlogo.gif" 58 _nist_logo = "images/nist_logo.png" 59 _umd_logo = "images/umd_logo.png" 60 _sns_logo = "images/sns_logo.png" 61 _isis_logo = "images/isis_logo.png" 62 _ess_logo = "images/ess_logo.png" 63 _ill_logo = "images/ill_logo.png" 75 64 _nist_url = "http://www.nist.gov/" 76 65 _umd_url = "http://www.umd.edu/" 77 66 _sns_url = "http://neutrons.ornl.gov/" 78 _ornl_url = "http://neutrons.ornl.gov/"79 67 _nsf_url = "http://www.nsf.gov" 68 _danse_url = "http://www.cacr.caltech.edu/projects/danse/release/index.html" 69 _inst_url = "http://www.utk.edu" 80 70 _isis_url = "http://www.isis.stfc.ac.uk/" 81 71 _ess_url = "http://ess-scandinavia.eu/" 82 72 _ill_url = "http://www.ill.eu/" 83 _ansto_url = "http://www.ansto.gov.au/" 84 _tudelft_url = "http://www.tnw.tudelft.nl/en/cooperation/facilities/reactor-instituut-delft/" 85 _danse_url = "http://www.cacr.caltech.edu/projects/danse/release/index.html" 86 _inst_url = "http://www.utk.edu" 87 _corner_image = os.path.join(icon_path, "angles_flat.png") 88 _welcome_image = os.path.join(icon_path, "SVwelcome.png") 89 _copyright = "(c) 2009 - 2017, UTK, UMD, NIST, ORNL, ISIS, ESS, ILL, ANSTO and TU Delft" 90 marketplace_url = "http://marketplace.sasview.org/" 91 92 #edit the list of file state your plugin can read 93 APPLICATION_WLIST = 'SasView files (*.svs)|*.svs' 94 APPLICATION_STATE_EXTENSION = '.svs' 95 GUIFRAME_WIDTH = 1150 96 GUIFRAME_HEIGHT = 840 97 PLUGIN_STATE_EXTENSIONS = ['.fitv', '.inv', '.prv', '.crf'] 98 PLUGINS_WLIST = ['Fitting files (*.fitv)|*.fitv', 99 'Invariant files (*.inv)|*.inv', 100 'P(r) files (*.prv)|*.prv', 101 'Corfunc files (*.crf)|*.crf'] 102 PLOPANEL_WIDTH = 415 103 PLOPANEL_HEIGTH = 370 73 _corner_image = "images/angles_flat.png" 74 _welcome_image = "images/SVwelcome.png" 75 _copyright = "(c) 2008, University of Tennessee" 76 #edit the lists below of file state your plugin can read 77 #for sasview this how you can edit these lists 78 #PLUGIN_STATE_EXTENSIONS = ['.prv','.fitv', '.inv'] 79 #APPLICATION_STATE_EXTENSION = '.svs' 80 #PLUGINS_WLIST = ['P(r) files (*.prv)|*.prv', 81 # 'Fitting files (*.fitv)|*.fitv', 82 # 'Invariant files (*.inv)|*.inv'] 83 #APPLICATION_WLIST = 'SasView files (*.svs)|*.svs' 84 APPLICATION_WLIST = '' 85 APPLICATION_STATE_EXTENSION = None 86 PLUGINS_WLIST = [] 87 PLUGIN_STATE_EXTENSIONS = [] 88 SPLASH_SCREEN_PATH = "images/danse_logo.png" 89 DEFAULT_STYLE = GUIFRAME.SINGLE_APPLICATION 90 SPLASH_SCREEN_WIDTH = 500 91 SPLASH_SCREEN_HEIGHT = 300 92 WELCOME_PANEL_ON = False 93 TUTORIAL_PATH = None 94 SS_MAX_DISPLAY_TIME = 1500 95 PLOPANEL_WIDTH = 350 96 PLOPANEL_HEIGTH = 350 97 GUIFRAME_WIDTH = 1000 98 GUIFRAME_HEIGHT = 800 99 CONTROL_WIDTH = -1 100 CONTROL_HEIGHT = -1 101 SetupIconFile_win = os.path.join("images", "ball.ico") 102 SetupIconFile_mac = os.path.join("images", "ball.icns") 103 DefaultGroupName = "DANSE" 104 OutputBaseFilename = "setupGuiFrame" 104 105 DATAPANEL_WIDTH = 235 105 106 DATAPANEL_HEIGHT = 700 106 SPLASH_SCREEN_PATH = os.path.join(icon_path, "SVwelcome_mini.png")107 TUTORIAL_PATH = os.path.join(media_path, "Tutorial.pdf")108 DEFAULT_STYLE = GUIFRAME.MULTIPLE_APPLICATIONS|GUIFRAME.MANAGER_ON\109 |GUIFRAME.CALCULATOR_ON|GUIFRAME.TOOLBAR_ON110 SPLASH_SCREEN_WIDTH = 512111 SPLASH_SCREEN_HEIGHT = 366112 SS_MAX_DISPLAY_TIME = 2000113 WELCOME_PANEL_ON = True114 WELCOME_PANEL_SHOW = False115 CLEANUP_PLOT = False116 # OPEN and SAVE project menu117 OPEN_SAVE_PROJECT_MENU = True118 #VIEW MENU119 VIEW_MENU = True120 #EDIT MENU121 EDIT_MENU = True122 123 SetupIconFile_win = os.path.join(icon_path, "ball.ico")124 SetupIconFile_mac = os.path.join(icon_path, "ball.icns")125 DefaultGroupName = "."126 OutputBaseFilename = "setupSasView"127 128 107 FIXED_PANEL = True 129 108 DATALOADER_SHOW = True … … 134 113 # set a default perspective 135 114 DEFAULT_PERSPECTIVE = 'None' 136 137 # Time out for updating sasview 138 UPDATE_TIMEOUT = 2 139 140 #OpenCL option 141 SAS_OPENCL = None 115 # OPEN and SAVE project menu 116 OPEN_SAVE_PROJECT_MENU = True 117 CLEANUP_PLOT = False 118 # OPEN and SAVE project menu 119 OPEN_SAVE_PROJECT_MENU = False 120 #VIEW MENU 121 VIEW_MENU = False 122 #EDIT MENU 123 EDIT_MENU = False 124 import wx.lib.newevent 125 (StatusBarEvent, EVT_STATUS) = wx.lib.newevent.NewEvent() 142 126 143 127 def printEVT(message): 128 """ 129 :TODO - need method documentation 130 """ 144 131 if __EVT_DEBUG__: 145 """146 :TODO - Need method doc string147 """148 132 print "%g: %s" % (time.clock(), message) 149 133 150 134 if __EVT_DEBUG_2_FILE__: 151 135 out = open(__EVT_DEBUG_FILENAME__, 'a') 152 136 out.write("%10g: %s\n" % (time.clock(), message)) 153 137 out.close() 138 -
src/sas/sasgui/guiframe/dataFitting.py
r68adf86 r345e7e4 17 17 """ 18 18 """ 19 20 def __init__(self, x=None, y=None, dx=None, dy=None, lam=None, dlam=None, isSesans=False): 19 def __init__(self, x=None, y=None, dx=None, dy=None): 21 20 """ 22 21 """ … … 25 24 if y is None: 26 25 y = [] 27 self.isSesans = isSesans 28 PlotData1D.__init__(self, x, y, dx, dy, lam, dlam) 29 LoadData1D.__init__(self, x, y, dx, dy, lam, dlam, isSesans) 30 26 PlotData1D.__init__(self, x, y, dx, dy) 27 LoadData1D.__init__(self, x, y, dx, dy) 31 28 self.id = None 32 29 self.list_group_id = [] … … 35 32 self.path = None 36 33 self.xtransform = None 37 if self.isSesans:38 self.xtransform = "x"39 34 self.ytransform = None 40 if self.isSesans:41 self.ytransform = "y"42 35 self.title = "" 43 36 self.scale = None … … 75 68 # First, check the data compatibility 76 69 dy, dy_other = self._validity_check(other) 77 result = Data1D(x=[], y=[], lam=[], dx=None, dy=None, dlam=None)70 result = Data1D(x=[], y=[], dx=None, dy=None) 78 71 result.clone_without_data(length=len(self.x), clone=self) 79 72 result.copy_from_datainfo(data1d=self) … … 122 115 # First, check the data compatibility 123 116 self._validity_check_union(other) 124 result = Data1D(x=[], y=[], lam=[], dx=None, dy=None, dlam=None)117 result = Data1D(x=[], y=[], dx=None, dy=None) 125 118 tot_length = len(self.x) + len(other.x) 126 119 result = self.clone_without_data(length=tot_length, clone=result) 127 if self.dlam == None or other.dlam is None:128 result.dlam = None129 else:130 result.dlam = numpy.zeros(tot_length)131 120 if self.dy == None or other.dy is None: 132 121 result.dy = None … … 152 141 result.y = numpy.append(self.y, other.y) 153 142 result.y = result.y[ind] 154 result.lam = numpy.append(self.lam, other.lam)155 result.lam = result.lam[ind]156 if result.dlam != None:157 result.dlam = numpy.append(self.dlam, other.dlam)158 result.dlam = result.dlam[ind]159 143 if result.dy != None: 160 144 result.dy = numpy.append(self.dy, other.dy) … … 276 260 # First, check the data compatibility 277 261 self._validity_check_union(other) 278 result = Data1D(x=[], y=[], lam=[], dx=None, dy=None, dlam=[])262 result = Data1D(x=[], y=[], dx=None, dy=None) 279 263 tot_length = len(self.x)+len(other.x) 280 264 result.clone_without_data(length=tot_length, clone=self) 281 if self.dlam == None or other.dlam is None:282 result.dlam = None283 else:284 result.dlam = numpy.zeros(tot_length)285 265 if self.dy == None or other.dy is None: 286 266 result.dy = None … … 305 285 result.y = numpy.append(self.y, other.y) 306 286 result.y = result.y[ind] 307 result.lam = numpy.append(self.lam, other.lam)308 result.lam = result.lam[ind]309 287 if result.dy != None: 310 288 result.dy = numpy.append(self.dy, other.dy) -
src/sas/sasgui/guiframe/data_manager.py
r2ffe241 r345e7e4 61 61 62 62 if issubclass(Data2D, data.__class__): 63 new_plot = Data2D(image=None, err_image=None) # For now, isSesans for 2D data is always false 64 else: 65 new_plot = Data1D(x=[], y=[], dx=None, dy=None, lam=None, dlam=None, isSesans=data.isSesans) 66 67 68 #elif data.meta_data['loader'] == 'SESANS': 69 # new_plot = Data1D(x=[], y=[], dx=None, dy=None, lam=None, dlam=None, isSesans=True) 70 #else: 71 # new_plot = Data1D(x=[], y=[], dx=None, dy=None, lam=None, dlam=None) #SESANS check??? 72 63 new_plot = Data2D(image=None, err_image=None) 64 else: 65 new_plot = Data1D(x=[], y=[], dx=None, dy=None) 66 73 67 new_plot.copy_from_datainfo(data) 74 68 data.clone_without_data(clone=new_plot) -
src/sas/sasgui/guiframe/data_panel.py
ra45a298 rc8e1996 66 66 IS_MAC = True 67 67 68 STYLE_FLAG = (wx.RAISED_BORDER | CT.TR_HAS_BUTTONS |69 wx.WANTS_CHARS | CT.TR_HAS_VARIABLE_ROW_HEIGHT )68 STYLE_FLAG = wx.RAISED_BORDER | CT.TR_HAS_BUTTONS | CT.TR_HIDE_ROOT |\ 69 wx.WANTS_CHARS | CT.TR_HAS_VARIABLE_ROW_HEIGHT 70 70 71 71 … … 74 74 Check list control to be used for Data Panel 75 75 """ 76 def __init__(self, parent, root,*args, **kwds):76 def __init__(self, parent, *args, **kwds): 77 77 # agwstyle is introduced in wx.2.8.11 but is not working for mac 78 78 if IS_MAC and wx_version < 812: … … 97 97 del kwds['style'] 98 98 CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds) 99 self.root = self.AddRoot( root)99 self.root = self.AddRoot("Available Data") 100 100 101 101 def OnCompareItems(self, item1, item2): … … 520 520 Add a listcrtl in the panel 521 521 """ 522 # Add splitter 523 w, h = self.parent.GetSize() 524 splitter = wx.SplitterWindow(self) 525 splitter.SetMinimumPaneSize(50) 526 splitter.SetSashGravity(1.0) 527 528 file_sizer = wx.BoxSizer(wx.VERTICAL) 529 file_sizer.SetMinSize(wx.Size(w/13, h*2/5)) 530 theory_sizer = wx.BoxSizer(wx.VERTICAL) 531 theory_sizer.SetMinSize(wx.Size(w/13, h*2/5)) 532 533 self.tree_ctrl = DataTreeCtrl(parent=splitter, 534 style=wx.SUNKEN_BORDER, 535 root="Available Data") 536 522 tree_ctrl_label = wx.StaticText(self, -1, "Data") 523 tree_ctrl_label.SetForegroundColour('blue') 524 self.tree_ctrl = DataTreeCtrl(parent=self, style=wx.SUNKEN_BORDER) 537 525 self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item) 538 526 self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_MENU, self.on_right_click_data) … … 569 557 wx.EVT_MENU(self, self.editmask_id, self.on_edit_data) 570 558 571 self.tree_ctrl_theory = DataTreeCtrl(parent=splitter, 572 style=wx.SUNKEN_BORDER, 573 root="Available Theory") 559 tree_ctrl_theory_label = wx.StaticText(self, -1, "Theory") 560 tree_ctrl_theory_label.SetForegroundColour('blue') 561 self.tree_ctrl_theory = DataTreeCtrl(parent=self, 562 style=wx.SUNKEN_BORDER) 574 563 self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_CHECKING, 575 564 self.on_check_item) 576 565 self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_MENU, 577 566 self.on_right_click_theory) 578 splitter.SplitHorizontally(self.tree_ctrl, self.tree_ctrl_theory) 579 self.sizer1.Add(splitter, 1, wx.EXPAND | wx.ALL, 10) 567 self.sizer1.Add(tree_ctrl_label, 0, wx.LEFT, 10) 568 self.sizer1.Add(self.tree_ctrl, 1, wx.EXPAND | wx.ALL, 10) 569 self.sizer1.Add(tree_ctrl_theory_label, 0, wx.LEFT, 10) 570 self.sizer1.Add(self.tree_ctrl_theory, 1, wx.EXPAND | wx.ALL, 10) 580 571 581 572 def on_right_click_theory(self, event): … … 731 722 if self.tree_ctrl.root: 732 723 self.tree_ctrl.SortChildren(self.tree_ctrl.root) 733 # Expand root if # of data sets > 0734 if self.tree_ctrl.GetCount() > 0:735 self.tree_ctrl.root.Expand()736 724 self.enable_remove() 737 725 self.enable_import() … … 772 760 state_id=state_id, 773 761 theory_list=theory_list) 774 if self.tree_ctrl_theory.GetCount() > 0:775 self.tree_ctrl_theory.root.Expand()776 762 777 763 def append_theory_helper(self, tree, root, state_id, theory_list): -
src/sas/sasgui/perspectives/calculator/model_editor.py
rddbac66 ra08b89b 5 5 function of y (usually the intensity). It also provides a drop down of 6 6 standard available math functions. Finally a full python editor panel for 7 complete customizati on is provided.8 9 :TODO the writi ng of the file and name checking (and maybe some other10 fun ctions?) should be moved to a computational module which could be called11 fro m a python script. Basically one just needs to pass the name,7 complete customizatin is provided. 8 9 :TODO the writiong of the file and name checking (and maybe some other 10 funtions?) should be moved to a computational module which could be called 11 fropm a python script. Basically one just needs to pass the name, 12 12 description text and function text (or in the case of the composite editor 13 13 the names of the first and second model and the operator to be used). … … 61 61 """ 62 62 Dialog for easy custom composite models. Provides a wx.Dialog panel 63 to choose two existing models (including pre-existing Plugin Models which63 to choose two existing models (including pre-existing custom models which 64 64 may themselves be composite models) as well as an operation on those models 65 65 (add or multiply) the resulting model will add a scale parameter for summed … … 380 380 color = 'blue' 381 381 except: 382 msg = "Easy Sum/Multipy Plugin: Error occurred..."382 msg = "Easy Custom Sum/Multipy: Error occurred..." 383 383 info = 'Error' 384 384 color = 'red' … … 501 501 self.factor = factor 502 502 self._operator = operator 503 self.explanation = " PluginModel = %s %s (model1 %s model2)\n" % \503 self.explanation = " Custom Model = %s %s (model1 %s model2)\n" % \ 504 504 (self.factor, f_oper, self._operator) 505 505 self.explanationctr.SetLabel(self.explanation) … … 617 617 class EditorPanel(wx.ScrolledWindow): 618 618 """ 619 Simple Plugin Model function editor619 Custom model function editor 620 620 """ 621 621 def __init__(self, parent, base, path, title, *args, **kwds): … … 652 652 self.msg_sizer = None 653 653 self.warning = "" 654 #This does not seem to be used anywhere so commenting out for now 655 # -- PDB 2/26/17 656 #self._description = "New Plugin Model" 654 self._description = "New Custom Model" 657 655 self.function_tcl = None 658 656 self.math_combo = None … … 993 991 else: 994 992 self._notes = result 995 msg = "Successful! Please look for %s in PluginModels."%name993 msg = "Successful! Please look for %s in Customized Models."%name 996 994 msg += " " + self._notes 997 995 info = 'Info' … … 1140 1138 def on_help(self, event): 1141 1139 """ 1142 Bring up the New PluginModel Editor Documentation whenever1140 Bring up the Custom Model Editor Documentation whenever 1143 1141 the HELP button is clicked. 1144 1142 … … 1192 1190 #self.Destroy() 1193 1191 1194 ## Templates for pluginmodels1192 ## Templates for custom models 1195 1193 1196 1194 CUSTOM_TEMPLATE = """ -
src/sas/sasgui/perspectives/calculator/pyconsole.py
rddbac66 rd472e86 302 302 success = show_model_output(self, fname) 303 303 304 # Update pluginmodel list in fitpage combobox304 # Update custom model list in fitpage combobox 305 305 if success and self._manager != None and self.panel != None: 306 306 self._manager.set_edit_menu_helper(self.parent) -
src/sas/sasgui/perspectives/fitting/basepage.py
rb301db9 r1a8e13f0 53 53 ON_MAC = True 54 54 55 CUSTOM_MODEL = 'Plugin Models'56 57 55 class BasicPage(ScrolledPanel, PanelBase): 58 56 """ 59 This class provide general structure of thefitpanel page57 This class provide general structure of fitpanel page 60 58 """ 61 59 # Internal name for the AUI manager … … 120 118 self.dxw = None 121 119 # pinhole smear 122 self.dx_percent = None 120 self.dx_min = None 121 self.dx_max = None 123 122 # smear attrbs 124 123 self.enable_smearer = None … … 678 677 def _copy_info(self, flag): 679 678 """ 680 Send event d epending on flag681 682 : Param flag: flag that distinguish es theevent679 Send event dpemding on flag 680 681 : Param flag: flag that distinguish event 683 682 """ 684 683 # messages depending on the flag … … 848 847 self.state.pinhole_smearer = \ 849 848 copy.deepcopy(self.pinhole_smearer.GetValue()) 850 self.state.dx_percent = copy.deepcopy(self.dx_percent) 849 self.state.dx_max = copy.deepcopy(self.dx_max) 850 self.state.dx_min = copy.deepcopy(self.dx_min) 851 851 self.state.dxl = copy.deepcopy(self.dxl) 852 852 self.state.dxw = copy.deepcopy(self.dxw) … … 1119 1119 :precondition: the page is already drawn or created 1120 1120 1121 :postcondition: the state of the underlying data change sas well as the1121 :postcondition: the state of the underlying data change as well as the 1122 1122 state of the graphic interface 1123 1123 """ … … 1167 1167 self._show_combox(None) 1168 1168 from models import PLUGIN_NAME_BASE 1169 if self.categorybox.GetValue() == CUSTOM_MODEL\1169 if self.categorybox.GetValue() == 'Customized Models' \ 1170 1170 and PLUGIN_NAME_BASE not in state.formfactorcombobox: 1171 1171 state.formfactorcombobox = \ … … 1245 1245 # we have two more options for smearing 1246 1246 if self.pinhole_smearer.GetValue(): 1247 self.dx_percent = state.dx_percent 1248 if self.dx_percent is not None: 1249 if state.dx_old: 1250 self.dx_percent = 100 * (self.dx_percent / self.data.x[0]) 1251 self.smear_pinhole_percent.SetValue("%.2f" % self.dx_percent) 1247 self.dx_min = state.dx_min 1248 self.dx_max = state.dx_max 1249 if self.dx_min is not None: 1250 self.smear_pinhole_min.SetValue(str(self.dx_min)) 1251 if self.dx_max is not None: 1252 self.smear_pinhole_max.SetValue(str(self.dx_max)) 1252 1253 self.onPinholeSmear(event=None) 1253 1254 elif self.slit_smearer.GetValue(): … … 1334 1335 def _selectDlg(self): 1335 1336 """ 1336 open a dialog file to select the customized polydispersity function1337 open a dialog file to selected the customized dispersity 1337 1338 """ 1338 1339 if self.parent is not None: … … 1746 1747 def _set_multfactor_combobox(self, multiplicity=10): 1747 1748 """ 1748 Set comboBox for mu ltitfactor of CoreMultiShellModel1749 Set comboBox for muitfactor of CoreMultiShellModel 1749 1750 :param multiplicit: no. of multi-functionality 1750 1751 """ … … 1784 1785 Fill panel's combo box according to the type of model selected 1785 1786 """ 1786 1787 custom_model = 'Customized Models' 1787 1788 mod_cat = self.categorybox.GetStringSelection() 1788 1789 self.structurebox.SetSelection(0) … … 1793 1794 m_list = [] 1794 1795 try: 1795 if mod_cat == CUSTOM_MODEL:1796 if mod_cat == custom_model: 1796 1797 for model in self.model_list_box[mod_cat]: 1797 1798 m_list.append(self.model_dict[model.name]) … … 3429 3430 fills out the category list box 3430 3431 """ 3431 uncat_str = ' PluginModels'3432 uncat_str = 'Customized Models' 3432 3433 self._read_category_info() 3433 3434 … … 3458 3459 self.model_box.Clear() 3459 3460 3460 if category == ' PluginModels':3461 if category == 'Customized Models': 3461 3462 for model in self.model_list_box[category]: 3462 3463 str_m = str(model).split(".")[0] -
src/sas/sasgui/perspectives/fitting/fitpage.py
rd85f1d8a r1a8e13f0 29 29 _BOX_WIDTH = 76 30 30 _DATA_BOX_WIDTH = 300 31 SMEAR_SIZE_L = 0.00 31 32 SMEAR_SIZE_H = 0.00 32 CUSTOM_MODEL = 'Plugin Models' 33 33 34 34 35 class FitPage(BasicPage): … … 163 164 On_select_data 164 165 """ 165 if self.dataSource.GetCount() > 0: 166 pos = self.dataSource.GetSelection() if event is not None else 0 166 if event is None and self.dataSource.GetCount() > 0: 167 data = self.dataSource.GetClientData(0) 168 self.set_data(data) 169 elif self.dataSource.GetCount() > 0: 170 pos = self.dataSource.GetSelection() 167 171 data = self.dataSource.GetClientData(pos) 168 172 self.set_data(data) … … 209 213 "Please enter only the value of interest to customize smearing..." 210 214 smear_message_new_psmear = \ 211 "Please enter a fixed percentage to be applied to all Q values..."215 "Please enter both; the dQ will be generated by interpolation..." 212 216 smear_message_2d_x_title = "<dQp>[1/A]:" 213 217 smear_message_2d_y_title = "<dQs>[1/A]:" 214 smear_message_pinhole_percent_title = "dQ[%]:" 218 smear_message_pinhole_min_title = "dQ_low[1/A]:" 219 smear_message_pinhole_max_title = "dQ_high[1/A]:" 215 220 smear_message_slit_height_title = "Slit height[1/A]:" 216 221 smear_message_slit_width_title = "Slit width[1/A]:" … … 251 256 self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting, 252 257 id=self.dI_idata.GetId()) 253 self.dI_ noweight.SetValue(True)258 self.dI_didata.SetValue(True) 254 259 # add 4 types of weighting to the sizer 255 260 sizer_weighting.Add(self.dI_noweight, 0, wx.LEFT, 10) … … 261 266 sizer_weighting.Add(self.dI_idata) 262 267 sizer_weighting.Add((10, 10)) 263 self.dI_noweight.Enable( True)268 self.dI_noweight.Enable(False) 264 269 self.dI_didata.Enable(False) 265 270 self.dI_sqrdata.Enable(False) … … 305 310 306 311 # textcntrl for custom resolution 307 self.smear_pinhole_percent = ModelTextCtrl(self, wx.ID_ANY, 308 size=(_BOX_WIDTH - 25, 20), 309 style=wx.TE_PROCESS_ENTER, 310 text_enter_callback= 311 self.onPinholeSmear) 312 self.smear_pinhole_max = ModelTextCtrl(self, wx.ID_ANY, 313 size=(_BOX_WIDTH - 25, 20), 314 style=wx.TE_PROCESS_ENTER, 315 text_enter_callback=self.onPinholeSmear) 316 self.smear_pinhole_min = ModelTextCtrl(self, wx.ID_ANY, 317 size=(_BOX_WIDTH - 25, 20), 318 style=wx.TE_PROCESS_ENTER, 319 text_enter_callback=self.onPinholeSmear) 312 320 self.smear_slit_height = ModelTextCtrl(self, wx.ID_ANY, 313 321 size=(_BOX_WIDTH - 25, 20), … … 328 336 329 337 # set default values for smear 330 self.smear_pinhole_percent.SetValue(str(self.dx_percent)) 338 self.smear_pinhole_max.SetValue(str(self.dx_max)) 339 self.smear_pinhole_min.SetValue(str(self.dx_min)) 331 340 self.smear_slit_height.SetValue(str(self.dxl)) 332 341 self.smear_slit_width.SetValue(str(self.dxw)) … … 353 362 self.Bind(wx.EVT_RADIOBUTTON, self.onSlitSmear, 354 363 id=self.slit_smearer.GetId()) 355 self. disable_smearer.SetValue(True)364 self.enable_smearer.SetValue(True) 356 365 357 366 sizer_smearer.Add(self.disable_smearer, 0, wx.LEFT, 10) … … 420 429 self.smear_description_2d_y.SetToolTipString( 421 430 " dQs(perpendicular) in q_phi direction.") 422 self.smear_description_pin_percent = wx.StaticText(self, wx.ID_ANY, 423 smear_message_pinhole_percent_title, 424 style=wx.ALIGN_LEFT) 431 self.smear_description_pin_min = wx.StaticText(self, wx.ID_ANY, 432 smear_message_pinhole_min_title, style=wx.ALIGN_LEFT) 433 self.smear_description_pin_max = wx.StaticText(self, wx.ID_ANY, 434 smear_message_pinhole_max_title, style=wx.ALIGN_LEFT) 425 435 self.smear_description_slit_height = wx.StaticText(self, wx.ID_ANY, 426 436 smear_message_slit_height_title, style=wx.ALIGN_LEFT) … … 446 456 self.sizer_new_smear.Add((15, -1)) 447 457 self.sizer_new_smear.Add(self.smear_description_2d_x, 0, wx.CENTER, 10) 458 self.sizer_new_smear.Add(self.smear_description_pin_min, 459 0, wx.CENTER, 10) 448 460 self.sizer_new_smear.Add(self.smear_description_slit_height, 449 461 0, wx.CENTER, 10) 450 462 463 self.sizer_new_smear.Add(self.smear_pinhole_min, 0, wx.CENTER, 10) 451 464 self.sizer_new_smear.Add(self.smear_slit_height, 0, wx.CENTER, 10) 452 465 self.sizer_new_smear.Add(self.smear_data_left, 0, wx.CENTER, 10) … … 454 467 self.sizer_new_smear.Add(self.smear_description_2d_y, 455 468 0, wx.CENTER, 10) 456 self.sizer_new_smear.Add(self.smear_description_pin_ percent,469 self.sizer_new_smear.Add(self.smear_description_pin_max, 457 470 0, wx.CENTER, 10) 458 471 self.sizer_new_smear.Add(self.smear_description_slit_width, 459 472 0, wx.CENTER, 10) 460 473 461 self.sizer_new_smear.Add(self.smear_pinhole_ percent, 0, wx.CENTER, 10)474 self.sizer_new_smear.Add(self.smear_pinhole_max, 0, wx.CENTER, 10) 462 475 self.sizer_new_smear.Add(self.smear_slit_width, 0, wx.CENTER, 10) 463 476 self.sizer_new_smear.Add(self.smear_data_right, 0, wx.CENTER, 10) … … 1236 1249 wx.PostEvent(self.parent, new_event) 1237 1250 # update list of plugins if new plugin is available 1238 custom_model = CUSTOM_MODEL1251 custom_model = 'Customized Models' 1239 1252 mod_cat = self.categorybox.GetStringSelection() 1240 1253 if mod_cat == custom_model: … … 1258 1271 if copy_flag: 1259 1272 self.get_paste_params(copy_flag) 1260 wx.CallAfter(self._onDraw, None)1273 wx.CallAfter(self._onDraw, None) 1261 1274 1262 1275 else: … … 1571 1584 if self.dxw is None: 1572 1585 self.dxw = "" 1573 if self.dx_percent is None: 1574 self.dx_percent = SMEAR_SIZE_H 1586 if self.dx_min is None: 1587 self.dx_min = SMEAR_SIZE_L 1588 if self.dx_max is None: 1589 self.dx_max = SMEAR_SIZE_H 1575 1590 1576 1591 def _get_smear_info(self): … … 1612 1627 elif data.dxl is not None or data.dxw is not None: 1613 1628 self.smear_type = "Slit" 1614 if data.dxl is not None and n umpy.all(data.dxl, 0):1629 if data.dxl is not None and not numpy.all(data.dxl, 0): 1615 1630 self.dq_l = data.dxl[0] 1616 if data.dxw is not None and n umpy.all(data.dxw, 0):1631 if data.dxw is not None and not numpy.all(data.dxw, 0): 1617 1632 self.dq_r = data.dxw[0] 1618 1633 # return self.smear_type,self.dq_l,self.dq_r … … 1634 1649 self.smear_description_2d_y.Show(True) 1635 1650 if self.pinhole_smearer.GetValue(): 1636 self.smear_pinhole_percent.Show(True) 1651 self.smear_pinhole_min.Show(True) 1652 self.smear_pinhole_max.Show(True) 1637 1653 # smear from data 1638 1654 elif self.enable_smearer.GetValue(): … … 1645 1661 self.smear_description_slit_width.Show(True) 1646 1662 elif self.smear_type == 'Pinhole': 1647 self.smear_description_pin_percent.Show(True) 1663 self.smear_description_pin_min.Show(True) 1664 self.smear_description_pin_max.Show(True) 1648 1665 self.smear_description_smear_type.Show(True) 1649 1666 self.smear_description_type.Show(True) … … 1654 1671 if self.smear_type == 'Pinhole': 1655 1672 self.smear_message_new_p.Show(True) 1656 self.smear_description_pin_percent.Show(True) 1657 1658 self.smear_pinhole_percent.Show(True) 1673 self.smear_description_pin_min.Show(True) 1674 self.smear_description_pin_max.Show(True) 1675 1676 self.smear_pinhole_min.Show(True) 1677 self.smear_pinhole_max.Show(True) 1659 1678 # custom slit smear 1660 1679 elif self.slit_smearer.GetValue(): … … 1681 1700 self.smear_data_left.Hide() 1682 1701 self.smear_data_right.Hide() 1683 self.smear_description_pin_percent.Hide() 1684 self.smear_pinhole_percent.Hide() 1702 self.smear_description_pin_min.Hide() 1703 self.smear_pinhole_min.Hide() 1704 self.smear_description_pin_max.Hide() 1705 self.smear_pinhole_max.Hide() 1685 1706 self.smear_description_slit_height.Hide() 1686 1707 self.smear_slit_height.Hide() … … 1906 1927 1907 1928 # more disables for 2D 1908 di_flag = False1909 dq_flag = False1910 1929 if self.data.__class__.__name__ == "Data2D" or \ 1911 1930 self.enable2D: … … 1913 1932 self.pinhole_smearer.Enable(True) 1914 1933 self.default_mask = copy.deepcopy(self.data.mask) 1915 if self.data.err_data is not None \ 1916 and numpy.any(self.data.err_data): 1917 di_flag = True 1918 if self.data.dqx_data is not None \ 1919 and numpy.any(self.data.dqx_data): 1920 dq_flag = True 1934 if self.data.err_data is None or\ 1935 numpy.all(err == 1 for err in self.data.err_data) or \ 1936 not numpy.any(self.data.err_data): 1937 self.dI_didata.Enable(False) 1938 self.dI_noweight.SetValue(True) 1939 self.weightbt_string = self.dI_noweight.GetLabelText() 1940 else: 1941 self.dI_didata.Enable(True) 1942 self.dI_didata.SetValue(True) 1943 self.weightbt_string = self.dI_didata.GetLabelText() 1921 1944 else: 1922 1945 self.slit_smearer.Enable(True) 1923 1946 self.pinhole_smearer.Enable(True) 1924 if self.data.dy is not None and numpy.any(self.data.dy): 1925 di_flag = True 1926 if self.data.dx is not None and numpy.any(self.data.dx): 1927 dq_flag = True 1928 elif self.data.dxl is not None and numpy.any(self.data.dxl): 1929 dq_flag = True 1930 1931 if dq_flag: 1932 self.enable_smearer.Enable(True) 1933 self.enable_smearer.SetValue(True) 1934 self.disable_smearer.SetValue(False) 1935 else: 1936 self.enable_smearer.Disable() 1937 self.disable_smearer.Enable(True) 1938 self.disable_smearer.SetValue(True) 1939 1940 if di_flag: 1941 self.dI_didata.Enable(True) 1942 self.dI_didata.SetValue(True) 1943 self.weightbt_string = self.dI_didata.GetLabelText() 1944 else: 1945 self.dI_didata.Enable(False) 1946 self.dI_noweight.SetValue(True) 1947 self.weightbt_string = self.dI_noweight.GetLabelText() 1948 1947 1948 if self.data.dy is None or\ 1949 numpy.all(self.data.dy == 1) or\ 1950 not numpy.any(self.data.dy): 1951 self.dI_didata.Enable(False) 1952 self.dI_noweight.SetValue(True) 1953 self.weightbt_string = self.dI_noweight.GetLabelText() 1954 else: 1955 self.dI_didata.Enable(True) 1956 self.dI_didata.SetValue(True) 1957 self.weightbt_string = self.dI_didata.GetLabelText() 1949 1958 # Enable weighting radio buttons 1950 1959 self.dI_noweight.Enable(True) … … 1988 1997 self.EditMask_title.Disable() 1989 1998 1990 self.on_smear_helper()1991 1999 self.on_set_focus(None) 1992 2000 self.Refresh() … … 2220 2228 # event case of radio button 2221 2229 if tcrtl.GetValue(): 2222 self.dx_percent = 0.0 2230 self.dx_min = 0.0 2231 self.dx_max = 0.0 2223 2232 is_new_pinhole = True 2224 2233 else: … … 2257 2266 """ 2258 2267 # get the values 2259 pin_percent = self.smear_pinhole_percent.GetValue() 2268 pin_min = self.smear_pinhole_min.GetValue() 2269 pin_max = self.smear_pinhole_max.GetValue() 2270 2271 # Check changes in slit width 2272 try: 2273 dx_min = float(pin_min) 2274 except: 2275 return True 2276 if self.dx_min != dx_min: 2277 return True 2260 2278 2261 2279 # Check changes in slit heigth 2262 2280 try: 2263 dx_ percent = float(pin_percent)2281 dx_max = float(pin_max) 2264 2282 except: 2265 2283 return True 2266 if self.dx_ percent != dx_percent:2284 if self.dx_max != dx_max: 2267 2285 return True 2268 2286 return False … … 2290 2308 msg = None 2291 2309 2292 get_pin_percent = self.smear_pinhole_percent 2293 2294 if not check_float(get_pin_percent): 2295 get_pin_percent.SetBackgroundColour("pink") 2310 get_pin_min = self.smear_pinhole_min 2311 get_pin_max = self.smear_pinhole_max 2312 2313 if not check_float(get_pin_min): 2314 get_pin_min.SetBackgroundColour("pink") 2315 msg = "Model Error:wrong value entered!!!" 2316 elif not check_float(get_pin_max): 2317 get_pin_max.SetBackgroundColour("pink") 2296 2318 msg = "Model Error:wrong value entered!!!" 2297 2319 else: 2298 2320 if len_data < 2: 2299 2321 len_data = 2 2300 self.dx_percent = float(get_pin_percent.GetValue()) 2301 if self.dx_percent < 0: 2302 get_pin_percent.SetBackgroundColour("pink") 2322 self.dx_min = float(get_pin_min.GetValue()) 2323 self.dx_max = float(get_pin_max.GetValue()) 2324 if self.dx_min < 0: 2325 get_pin_min.SetBackgroundColour("pink") 2303 2326 msg = "Model Error:This value can not be negative!!!" 2304 elif self.dx_percent is not None: 2305 percent = self.dx_percent/100 2327 elif self.dx_max < 0: 2328 get_pin_max.SetBackgroundColour("pink") 2329 msg = "Model Error:This value can not be negative!!!" 2330 elif self.dx_min is not None and self.dx_max is not None: 2306 2331 if self._is_2D(): 2307 data.dqx_data[data.dqx_data == 0] = percent * data.qx_data 2308 data.dqy_data[data.dqy_data == 0] = percent * data.qy_data 2332 data.dqx_data[data.dqx_data == 0] = self.dx_min 2333 data.dqy_data[data.dqy_data == 0] = self.dx_max 2334 elif self.dx_min == self.dx_max: 2335 data.dx[data.dx == 0] = self.dx_min 2309 2336 else: 2310 data.dx = percent * data.x 2337 step = (self.dx_max - self.dx_min) / (len_data - 1) 2338 data.dx = numpy.arange(self.dx_min, 2339 self.dx_max + step / 1.1, 2340 step) 2341 elif self.dx_min is not None: 2342 if self._is_2D(): 2343 data.dqx_data[data.dqx_data == 0] = self.dx_min 2344 else: 2345 data.dx[data.dx == 0] = self.dx_min 2346 elif self.dx_max is not None: 2347 if self._is_2D(): 2348 data.dqy_data[data.dqy_data == 0] = self.dx_max 2349 else: 2350 data.dx[data.dx == 0] = self.dx_max 2311 2351 self.current_smearer = smear_selection(data, self.model) 2312 2352 # 2D need to set accuracy … … 2318 2358 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 2319 2359 else: 2320 get_pin_percent.SetBackgroundColour("white") 2360 get_pin_min.SetBackgroundColour("white") 2361 get_pin_max.SetBackgroundColour("white") 2321 2362 # set smearing value whether or not the data contain the smearing info 2322 2363 -
src/sas/sasgui/perspectives/fitting/fitting.py
r4c5098c r1a8e13f0 225 225 226 226 self.id_edit = wx.NewId() 227 editmodel_help = "Edit customized model sample file" 227 228 self.menu1.AppendMenu(self.id_edit, "Plugin Model Operations", 228 self.edit_model_menu )229 self.edit_model_menu, editmodel_help) 229 230 #create menubar items 230 231 return [(self.menu1, self.sub_menu)] … … 259 260 self.update_custom_combo() 260 261 if os.path.isfile(p_path): 261 msg = "Sorry! unable to delete the default "262 msg += " pluginmodel... \n"262 msg = "Sorry! Could not be able to delete the default " 263 msg += "custom model... \n" 263 264 msg += "Please manually remove the files (.py, .pyc) " 264 265 msg += "in the 'plugin_models' folder \n" … … 273 274 if item.GetLabel() == label: 274 275 self.edit_menu.DeleteItem(item) 275 msg = "The pluginmodel, %s, has been deleted." % label276 msg = "The custom model, %s, has been deleted." % label 276 277 evt = StatusEvent(status=msg, type='stop', info='info') 277 278 wx.PostEvent(self.parent, evt) … … 330 331 temp = self.fit_panel.reset_pmodel_list() 331 332 if temp: 332 # Set the new pluginmodel list for all fit pages333 # Set the new custom model list for all fit pages 333 334 for uid, page in self.fit_panel.opened_pages.iteritems(): 334 335 if hasattr(page, "formfactorbox"): … … 1745 1746 data_id="Data " + data.name + " unsmeared", 1746 1747 dy=unsmeared_error) 1747 # Comment this out until we can get P*S models with correctly populated parameters 1748 #if sq_model is not None and pq_model is not None: 1749 # self.create_theory_1D(x, sq_model, page_id, model, data, state, 1750 # data_description=model.name + " S(q)", 1751 # data_id=str(page_id) + " " + data.name + " S(q)") 1752 # self.create_theory_1D(x, pq_model, page_id, model, data, state, 1753 # data_description=model.name + " P(q)", 1754 # data_id=str(page_id) + " " + data.name + " P(q)") 1748 1749 if sq_model is not None and pq_model is not None: 1750 self.create_theory_1D(x, sq_model, page_id, model, data, state, 1751 data_description=model.name + " S(q)", 1752 data_id=str(page_id) + " " + data.name + " S(q)") 1753 self.create_theory_1D(x, pq_model, page_id, model, data, state, 1754 data_description=model.name + " P(q)", 1755 data_id=str(page_id) + " " + data.name + " P(q)") 1756 1755 1757 1756 1758 current_pg = self.fit_panel.get_page_by_id(page_id) … … 1953 1955 ## then kill itself but cannot. Paul Kienzle came up with 1954 1956 ## this fix to prevent threads from stepping on each other 1955 ## which was causing a simple custom plugin model to crash 1956 ##Sasview. 1957 ## which was causing a simple custom model to crash Sasview. 1957 1958 ## We still don't know why the fit sometimes lauched a second 1958 1959 ## thread -- something which should also be investigated. -
src/sas/sasgui/perspectives/fitting/media/fitting_help.rst
r5295cf5 r26c8be3 34 34 * in *Single* fit mode - individual data sets are fitted independently one-by-one 35 35 36 * in *Simultaneous* fit mode - multiple data sets are fitted simultaneously to 37 the *same* model with/without constrained parameters (this might be useful, 38 for example, if you have measured the same sample at different contrasts) 36 * in *Simultaneous* fit mode - multiple data sets are fitted simultaneously to the *same* model with/without constrained parameters (this might be useful, for example, if you have measured the same sample at different contrasts) 39 37 40 38 * in *Batch* fit mode - multiple data sets are fitted sequentially to the *same* model (this might be useful, for example, if you have performed a kinetic or time-resolved experiment and have *lots* of data sets!) … … 45 43 ----------------- 46 44 47 The models in SasView are grouped into categories. By default these consist of: 48 49 * *Cylinder* - cylindrical shapes (disc, right cylinder, cylinder with endcaps 50 etc) 51 * *Ellipsoid* - ellipsoidal shapes (oblate,prolate, core shell, etc) 52 * *Parellelepiped* - as the name implies 53 * *Sphere* - sheroidal shapes (sphere, core multishell, vesicle, etc) 54 * *Lamellae* - lamellar shapes (lamellar, core shell lamellar, stacked 55 lamellar, etc) 45 By default, the models in SasView are grouped into five categories 46 47 * *Shapes* - models describing 'objects' (spheres, cylinders, etc) 56 48 * *Shape-Independent* - models describing structure in terms of density correlation functions, fractals, peaks, power laws, etc 57 * *Paracrystal* - semi ordered structures (bcc, fcc, etc) 49 * *Customized Models* - SasView- or User-created (non-library) Python models 50 * *Uncategorised* - other models (for reflectivity, etc) 58 51 * *Structure Factor* - S(Q) models 59 * *Plugin Models* - User-created (custom/non-library) Python models60 52 61 53 Use the *Category* drop-down menu to chose a category of model, then select … … 92 84 .. image:: cat_fig0.bmp 93 85 94 The categorization of all models except the user supplied Plugin Models can be95 reassigned, added to, and removed using *Category Manager*. Models can also be 96 hidden from viewin the drop-down menus.86 The categorization of all models except the customized models can be reassigned, 87 added to, and removed using *Category Manager*. Models can also be hidden from view 88 in the drop-down menus. 97 89 98 90 .. image:: cat_fig1.bmp … … 101 93 ^^^^^^^^^^^^^^^^^ 102 94 103 To change category, highlight a model in the list by left-clicking on its entry 104 and then click the *Modify* button. Use the *Change Category* panel that appears 105 t o make the required changes.95 To change category, highlight a model in the list by left-clicking on its entry and 96 then click the *Modify* button. Use the *Change Category* panel that appears to make 97 the required changes. 106 98 107 99 .. image:: cat_fig2.bmp … … 114 106 ^^^^^^^^^^^^^^^^^^^^^ 115 107 116 Use the *Enable All / Disable All* buttons and the check boxes beside each model 117 to select the models to show/hide. To apply the selection, click *Ok*. Otherwise 118 click*Cancel*.108 Use the *Enable All / Disable All* buttons and the check boxes beside each model to 109 select the models to show/hide. To apply the selection, click *Ok*. Otherwise click 110 *Cancel*. 119 111 120 112 *NB: It may be necessary to change to a different category and then back again* … … 126 118 --------------- 127 119 128 For a complete list of all the library models available in SasView, see 129 the `Model Documentation <../../../index.html>`_ . 120 For a complete list of all the library models available in SasView, see the `Model Documentation <../../../index.html>`_ . 130 121 131 122 It is also possible to add your own models. … … 140 131 There are essentially three ways to generate new fitting models for SasView: 141 132 142 * Using the SasView :ref:`New_Plugin_Model` helper dialog (best for beginners 143 and/or relatively simple models) 144 * By copying/editing an existing model (this can include models generated by 145 the New Plugin Model* dialog) in the :ref:`Python_shell` or 146 :ref:`Advanced_Plugin_Editor` (suitable for all use cases) 147 * By writing a model from scratch outside of SasView (only recommended for code 148 monkeys!) 133 * Using the SasView :ref:`New_Plugin_Model` helper dialog (best for beginners and/or relatively simple models) 134 * By copying/editing an existing model (this can include models generated by the *New Plugin Model* dialog) in the :ref:`Python_shell` or :ref:`Advanced_Plugin_Editor` (suitable for all use cases) 135 * By writing a model from scratch outside of SasView (only recommended for code monkeys!) 149 136 150 137 Please read the guidance on :ref:`Writing_a_Plugin` before proceeding. … … 176 163 ^^^^^^^^^^^^^^^^ 177 164 178 Relatively straightforward models can be programmed directly from the SasView 179 GUIusing the *New Plugin Model Function*.165 Relatively straightforward models can be programmed directly from the SasView GUI 166 using the *New Plugin Model Function*. 180 167 181 168 .. image:: new_model.bmp … … 188 175 *checked*\ . 189 176 190 Also note that the 'Fit Parameters' have been split into two sections: those 191 which can be polydisperse (shape and orientation parameters) and those which are 192 not(eg, scattering length densities).177 Also note that the 'Fit Parameters' have been split into two sections: those which 178 can be polydisperse (shape and orientation parameters) and those which are not 179 (eg, scattering length densities). 193 180 194 181 A model file generated by this option can be viewed and further modified using … … 200 187 .. image:: sum_model.bmp 201 188 202 This option creates a custom Plugin Model of the form::203 204 Plugin Model = scale_factor * {(scale_1 * model_1) +/- (scale_2 * model_2)}+ background189 This option creates a custom model of the form:: 190 191 Custom Model = scale_factor \* {(scale_1 \* model_1) \+ (scale_2 \* model_2)} \+ background 205 192 206 193 or:: 207 194 208 Plugin Model = scale_factor * model_1 /* model_2+ background195 Custom Model = scale_factor \* model_1 \* model_2 \+ background 209 196 210 197 In the *Easy Sum/Multi Editor* give the new model a function name and brief … … 245 232 Simply highlight the plugin model to be removed. The operation is final!!! 246 233 247 *NB: Models shipped with SasView cannot be removed in this way.*234 *NB: Plugin models shipped with SasView cannot be removed in this way.* 248 235 249 236 Load Plugin Models 250 237 ^^^^^^^^^^^^^^^^^^ 251 238 252 This option loads (or re-loads) all models present in the 253 *~\\.sasview\\plugin_models* folder. 239 This option loads (or re-loads) all models present in the *~\\.sasview\\plugin_models* folder. 254 240 255 241 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ … … 414 400 :ref:`Assessing_Fit_Quality`. 415 401 416 *NB: If you need to use a custom Plugin Model, you must ensure that model is417 availablefirst (see* :ref:`Adding_your_own_models` *).*402 *NB: If you need to use a customized model, you must ensure that model is available* 403 *first (see* :ref:`Adding_your_own_models` *).* 418 404 419 405 Method … … 498 484 If multiple data sets are in one file, load just that file. *Unselect All Data*, then 499 485 select a single initial data set to be fitted. Fit that selected data set as described 500 above under :ref:`Single_Fit_Mode` .501 502 *NB: If you need to use a custom Plugin Model, you must ensure that model is503 availablefirst (see* :ref:`Adding_your_own_models` *).*486 above under :ref:`Single_Fit_Mode` . 487 488 *NB: If you need to use a customized model, you must ensure that model is available* 489 *first (see* :ref:`Adding_your_own_models` *).* 504 490 505 491 Method -
src/sas/sasgui/perspectives/fitting/media/plugin.rst
r984f3fc rca6cbc1c 27 27 28 28 the next time SasView is started it will compile the plugin and add 29 it to the list of * PluginModels* in a FitPage.29 it to the list of *Customized Models* in a FitPage. 30 30 31 31 SasView models can be of three types: … … 364 364 - the limits will show up as the default limits for the fit making it easy, 365 365 for example, to force the radius to always be greater than zero. 366 367 - these are hard limits defining the valid range of parameter values;368 polydisperity distributions will be truncated at the limits.369 366 370 367 - **"type"** can be one of: "", "sld", "volume", or "orientation". -
src/sas/sasgui/perspectives/fitting/model_thread.py
rc1c9929 rc1681ea 177 177 unsmeared_output = numpy.zeros((len(self.data.x))) 178 178 unsmeared_output[first_bin:last_bin+1] = self.model.evalDistribution(mask) 179 self.smearer.model = self.model180 179 output = self.smearer(unsmeared_output, first_bin, last_bin) 181 180 -
src/sas/sasgui/perspectives/fitting/models.py
re92a352 r0de74af 325 325 self.plugins.append(plug) 326 326 self.model_dictionary[name] = plug 327 self.model_combobox.set_list(" PluginModels", self.plugins)327 self.model_combobox.set_list("Customized Models", self.plugins) 328 328 return self.model_combobox.get_list() 329 329 else: … … 346 346 self.model_dictionary[name] = plug 347 347 348 self.model_combobox.reset_list(" PluginModels", self.plugins)348 self.model_combobox.reset_list("Customized Models", self.plugins) 349 349 return self.model_combobox.get_list() 350 350 … … 389 389 # self.shape_indep_list) 390 390 self.model_combobox.set_list("Structure Factors", self.struct_list) 391 self.model_combobox.set_list(" PluginModels", self.plugins)391 self.model_combobox.set_list("Customized Models", self.plugins) 392 392 self.model_combobox.set_list("P(Q)*S(Q)", self.multiplication_factor) 393 393 self.model_combobox.set_list("multiplication", -
src/sas/sasgui/perspectives/fitting/pagestate.py
r27109e5 r6d2b50b 33 33 from sas.sascalc.dataloader.data_info import Data2D, Collimation, Detector 34 34 from sas.sascalc.dataloader.data_info import Process, Aperture 35 36 35 # Information to read/write state as xml 37 36 FITTING_NODE_NAME = 'fitting_plug_in' 38 37 CANSAS_NS = "cansas1d/1.0" 39 40 CUSTOM_MODEL = 'Plugin Models'41 CUSTOM_MODEL_OLD = 'Customized Models'42 38 43 39 LIST_OF_DATA_ATTRIBUTES = [["is_data", "is_data", "bool"], … … 74 70 ["dq_l", "dq_l", "float"], 75 71 ["dq_r", "dq_r", "float"], 76 ["dx_percent", "dx_percent", "float"], 72 ["dx_max", "dx_max", "float"], 73 ["dx_min", "dx_min", "float"], 77 74 ["dxl", "dxl", "float"], 78 75 ["dxw", "dxw", "float"]] … … 214 211 self.dq_l = None 215 212 self.dq_r = None 216 self.dx_ percent= None217 self.dx_ old = False213 self.dx_max = None 214 self.dx_min = None 218 215 self.dxl = None 219 216 self.dxw = None … … 342 339 obj.dq_l = copy.deepcopy(self.dq_l) 343 340 obj.dq_r = copy.deepcopy(self.dq_r) 344 obj.dx_ percent = copy.deepcopy(self.dx_percent)345 obj.dx_ old = copy.deepcopy(self.dx_old)341 obj.dx_max = copy.deepcopy(self.dx_max) 342 obj.dx_min = copy.deepcopy(self.dx_min) 346 343 obj.dxl = copy.deepcopy(self.dxl) 347 344 obj.dxw = copy.deepcopy(self.dxw) … … 369 366 :return: None 370 367 """ 371 if self.categorycombobox == CUSTOM_MODEL_OLD:372 self.categorycombobox = CUSTOM_MODEL373 368 if self.formfactorcombobox == '': 374 369 FIRST_FORM = { … … 383 378 'Sphere' : 'adsorbed_layer', 384 379 'Structure Factor' : 'hardsphere', 385 CUSTOM_MODEL: ''380 'Customized Models' : '' 386 381 } 387 382 if self.categorycombobox == '': … … 561 556 rep += "dq_l : %s\n" % self.dq_l 562 557 rep += "dq_r : %s\n" % self.dq_r 563 rep += "dx_percent : %s\n" % str(self.dx_percent) 558 rep += "dx_max : %s\n" % str(self.dx_max) 559 rep += "dx_min : %s\n" % str(self.dx_min) 564 560 rep += "dxl : %s\n" % str(self.dxl) 565 561 rep += "dxw : %s\n" % str(self.dxw) … … 819 815 820 816 attr = newdoc.createAttribute("version") 821 from sasimport sasview817 import sasview 822 818 attr.nodeValue = sasview.__version__ 823 819 # attr.nodeValue = '1.0' … … 1046 1042 setattr(self, item[0], parse_entry_helper(node, item)) 1047 1043 1048 dx_old_node = get_content('ns:%s' % 'dx_min', entry)1049 1044 for item in LIST_OF_STATE_ATTRIBUTES: 1050 if item[0] == "dx_percent" and dx_old_node is not None: 1051 dxmin = ["dx_min", "dx_min", "float"] 1052 setattr(self, item[0], parse_entry_helper(dx_old_node, 1053 dxmin)) 1054 self.dx_old = True 1055 else: 1056 node = get_content('ns:%s' % item[0], entry) 1057 setattr(self, item[0], parse_entry_helper(node, item)) 1045 node = get_content('ns:%s' % item[0], entry) 1046 setattr(self, item[0], parse_entry_helper(node, item)) 1058 1047 1059 1048 for item in LIST_OF_STATE_PARAMETERS: -
src/sas/sasgui/plottools/plottables.py
ra9f579c r345e7e4 1023 1023 """ 1024 1024 1025 def __init__(self, x, y, dx=None, dy=None , lam=None, dlam=None):1025 def __init__(self, x, y, dx=None, dy=None): 1026 1026 """ 1027 1027 Draw points specified by x[i],y[i] in the current color/symbol. … … 1037 1037 self.x = x 1038 1038 self.y = y 1039 self.lam = lam1040 1039 self.dx = dx 1041 1040 self.dy = dy 1042 self.dlam = dlam1043 1041 self.source = None 1044 1042 self.detector = None
Note: See TracChangeset
for help on using the changeset viewer.