shape2sas 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. shape2sas/__init__.py +1 -0
  2. shape2sas/cli.py +298 -0
  3. shape2sas/compare.py +222 -0
  4. shape2sas/helpfunctions.py +180 -0
  5. shape2sas/mixture.py +193 -0
  6. shape2sas/models.py +210 -0
  7. shape2sas/plots.py +217 -0
  8. shape2sas/sesans/__init__.py +9 -0
  9. shape2sas/sesans/sesans_calculations.py +43 -0
  10. shape2sas/sesans/sesans_helpfunctions.py +7 -0
  11. shape2sas/sesans/sesans_output.py +59 -0
  12. shape2sas/simulated_scattering.py +72 -0
  13. shape2sas/structure_factors/Aggregation.py +44 -0
  14. shape2sas/structure_factors/HardSphere.py +82 -0
  15. shape2sas/structure_factors/NoStructure.py +23 -0
  16. shape2sas/structure_factors/__init__.py +21 -0
  17. shape2sas/structure_factors/structure_factors_helpfunctions.py +63 -0
  18. shape2sas/subunits/CircularDisc.py +8 -0
  19. shape2sas/subunits/Cube.py +31 -0
  20. shape2sas/subunits/Cuboid.py +28 -0
  21. shape2sas/subunits/Cylinder.py +39 -0
  22. shape2sas/subunits/CylinderRing.py +51 -0
  23. shape2sas/subunits/Disc.py +8 -0
  24. shape2sas/subunits/Ellipsoid.py +38 -0
  25. shape2sas/subunits/Ellipsoid_shell.py +39 -0
  26. shape2sas/subunits/EllipticalCylinder.py +37 -0
  27. shape2sas/subunits/HollowCube.py +75 -0
  28. shape2sas/subunits/HollowSphere.py +56 -0
  29. shape2sas/subunits/Hyperboloid.py +36 -0
  30. shape2sas/subunits/Sphere.py +37 -0
  31. shape2sas/subunits/Superellipsoid.py +43 -0
  32. shape2sas/subunits/Torus.py +38 -0
  33. shape2sas/subunits/__init__.py +21 -0
  34. shape2sas/subunits/subunits_helpfunctions.py +15 -0
  35. shape2sas/theoretical_scattering.py +250 -0
  36. shape2sas-0.0.1.dist-info/METADATA +521 -0
  37. shape2sas-0.0.1.dist-info/RECORD +41 -0
  38. shape2sas-0.0.1.dist-info/WHEEL +5 -0
  39. shape2sas-0.0.1.dist-info/entry_points.txt +4 -0
  40. shape2sas-0.0.1.dist-info/licenses/LICENSE +674 -0
  41. shape2sas-0.0.1.dist-info/top_level.txt +1 -0
shape2sas/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "2.7.0"
shape2sas/cli.py ADDED
@@ -0,0 +1,298 @@
1
+ #!/usr/bin/python3
2
+
3
+ import time
4
+ import argparse
5
+ import sys
6
+ import numpy as np
7
+ import shutil
8
+
9
+ from . import __version__
10
+ from .helpfunctions import (
11
+ check_3Dinput,
12
+ check_input,
13
+ float_list,
14
+ get_header_footer,
15
+ getStructureFactorClass,
16
+ printt,
17
+ separate_string,
18
+ str2bool,
19
+ )
20
+ from .models import getPointDistribution, save_points
21
+ from .theoretical_scattering import (
22
+ calc_Iq_func,
23
+ calc_Pq_func,
24
+ calc_pr_func,
25
+ calc_S_func,
26
+ save_I_func,
27
+ save_pr_func,
28
+ )
29
+ from .structure_factors.structure_factors_helpfunctions import save_S_func
30
+ from .simulated_scattering import save_Isim_func, simulate_data_func
31
+ from .plots import generate_pdb, plot_2D, plot_fit, plot_results
32
+ from .sesans import calc_G_sesans, plot_sesans, save_sesans, simulate_sesans
33
+
34
+
35
+ def main(argv=None):
36
+ """Entry point for the ``shape2sas`` command."""
37
+ argv = sys.argv[1:] if argv is None else list(argv)
38
+
39
+ ### start timing
40
+ start_total = time.time()
41
+
42
+ ### remove any existing log file
43
+ open('shape2sas.log','w').close()
44
+
45
+ ### welcome message
46
+ printt('#######################################################################################')
47
+ printt('RUNNING shape2sas version %s \n - for instructions type: shape2sas -h' % __version__)
48
+ command = "shape2sas"
49
+ for aa in argv:
50
+ if ' ' in aa:
51
+ command += " \"%s\"" % aa
52
+ else:
53
+ command += " %s" % aa
54
+ printt('command used: %s' % command)
55
+ printt('#######################################################################################')
56
+
57
+ ### input values
58
+ parser = argparse.ArgumentParser(description='Shape2SaS - calculates small-angle scattering from a given shape defined by the user.')
59
+
60
+ # mandatory inputs
61
+ parser.add_argument('-s', '--subunit', type=separate_string, nargs='+', action='extend',
62
+ help='Type of subunits for each model.')
63
+ parser.add_argument('-d', '--dimension', type=float_list, nargs='+', action='append',
64
+ help='dimensions of subunits for each model.')
65
+
66
+ # optional model-dependent inputs:
67
+ parser.add_argument('-m', '--model_name', nargs='+', action='extend',
68
+ help='Name of model.')
69
+ parser.add_argument('-sld', '--sld', type=float, nargs='+', action='append',
70
+ help='excess scattering length density or contrast.')
71
+ parser.add_argument('-pd', '--polydispersity', type=float, nargs='+', action='extend',
72
+ help='Polydispersity of subunits for each model.')
73
+ parser.add_argument('-com', '--com', type=float_list, nargs='+', action='append',
74
+ help='displacement for each subunits in each model.')
75
+ parser.add_argument('-rot', '--rotation', type=float_list, nargs='+', action='append',
76
+ help='rotation for each subunits in each model.')
77
+ parser.add_argument('-rotp', '--rotation_points', type=float_list, nargs='+', action='append',
78
+ help='point to rotate around, for each subunit in each model (default: the subunit centre).')
79
+ parser.add_argument('-sigmar', '--sigma_r', type=float, nargs='+', action='extend',
80
+ help='interface roughness for each model.')
81
+ parser.add_argument('-c', '--conc', type=float, nargs='+', action='extend',
82
+ help='volume fraction concentration.')
83
+ parser.add_argument('-exclude', '--exclude_overlap', type=str2bool, nargs='+', action='extend',
84
+ help='bool to exclude overlap.')
85
+
86
+ # optional structure factor related inputs
87
+ parser.add_argument('-S', '--S', type=str, nargs='+', action='extend',
88
+ help='structure factor: None/HS/aggregation in each model.')
89
+ parser.add_argument('-Sp', '--S_par', type=float_list, nargs='+', action='append',
90
+ help='parameters of structure factor for each model.')
91
+
92
+ # optional general inputs
93
+ parser.add_argument('-qmin', '--qmin', type=float, default=0.001,
94
+ help='Minimum q-value for the scattering curve.')
95
+ parser.add_argument('-qmax', '--qmax', type=float, default=0.5,
96
+ help='Maximum q-value for the scattering curve.')
97
+ parser.add_argument('-Nq', '--qpoints', type=int, default=400,
98
+ help='Number of points in q.')
99
+ parser.add_argument('-Np', '--prpoints', type=int, default=100,
100
+ help='Number of points in the pair distance distribution function.')
101
+ parser.add_argument('-N', '--Npoints', type=int, default=8000,
102
+ help='Number of simulated points per model.')
103
+ parser.add_argument('-expo', '--exposure', type=float, default=500,
104
+ help='Exposure time in arbitrary units.')
105
+
106
+ # optional plot options
107
+ parser.add_argument('-lin', '--xscale_lin', action='store_true', default=False,
108
+ help='include flag (no input) to make q scale linear instead of logarithmic.')
109
+ parser.add_argument('-hres', '--high_res', action='store_true', default=False,
110
+ help='include flag (no input) to output high resolution plot.')
111
+
112
+ # optional SESANS-related options (Shape2SESANS)
113
+ parser.add_argument('-ss', '--sesans', action='store_true', default=False,
114
+ help='Calculate SESANS data from the SAS data.')
115
+ parser.add_argument('-sse', '--sesans_error', type=float, default=0.02,
116
+ help='Baseline SESANS error relative to max signal.')
117
+ parser.add_argument('-Nd', '--deltapoints', type=int, default=150,
118
+ help='Number of points in delta.')
119
+
120
+ # optional experimental data-related options (Shape2SAS-fit)
121
+ parser.add_argument('-dat','--data',
122
+ help='Path to experimental data')
123
+
124
+ args = parser.parse_args(argv)
125
+
126
+ ### check input
127
+
128
+ # check that subunits and dimensions are provided
129
+ if args.subunit is None:
130
+ raise argparse.ArgumentError(args.subunit, "No subunit type was given as an input.")
131
+ if args.dimension is None:
132
+ raise argparse.ArgumentError(args.dimension, "No dimensions were given as an input.")
133
+ # check that number of subunits matches number of dimension lists
134
+ for subunit, dimension in zip(args.subunit, args.dimension):
135
+ if len(subunit) != len(dimension):
136
+ raise argparse.ArgumentTypeError("Mismatch between number subunit types (%d) and dimensions lists (%d)." % (len(subunit),len(dimension)))
137
+ num_models = len(args.subunit)
138
+ if num_models == 1:
139
+ printt(f"Simulating {num_models} model...")
140
+ else:
141
+ printt(f"Simulating {num_models} models...")
142
+
143
+ # prepare lists (several models can be simulated simultaneously)
144
+ r_list, pr_norm_list, I_list, I_sim_list, sigma_list, S_list = [], [], [], [], [], []
145
+ x_list, y_list, z_list, sld_list, model_filename_list, model_name_list = [], [], [], [], [], []
146
+ if args.sesans:
147
+ delta_list,G_list,G_sim_list,sigma_G_list = [],[],[],[]
148
+
149
+ # loop over models
150
+ for i in range(num_models):
151
+
152
+ ### read and print model name for model i
153
+ model_name = check_input(args.model_name, f"Model {i}", "model name", i)
154
+ if model_name in model_name_list:
155
+ #model names should be unique - else add a number
156
+ model_name += '_' + str(i+1)
157
+ model_filename = "_".join(model_name.split()) # remove whitespace for filenames
158
+ model_name_list.append(model_name)
159
+ model_filename_list.append(model_filename)
160
+
161
+ #### read number of subunits, SLD, COM, rotation and exclude overlap for model i
162
+ N_subunits = len(args.subunit[i])
163
+ sld = check_3Dinput(args.sld, [1.0], "SLD", N_subunits, i)
164
+ com = check_3Dinput(args.com, [[0, 0, 0]], "COM", N_subunits, i)
165
+ rotation = check_3Dinput(args.rotation, [[0, 0, 0]], "rotation", N_subunits, i)
166
+ rotation_points = check_3Dinput(args.rotation_points, [[0, 0, 0]], "rotation points", N_subunits, i)
167
+ exclude_overlap = check_input(args.exclude_overlap, True, "exclude_overlap", i)
168
+
169
+ ### make point cloud
170
+ printt(f" Generating points for Model: " + model_name)
171
+ point_distribution = getPointDistribution(args.subunit[i],sld,args.dimension[i],com,rotation,exclude_overlap,args.Npoints,rotation_points)
172
+ save_points(point_distribution, model_filename)
173
+ x_list.append(np.concatenate(point_distribution.x))
174
+ y_list.append(np.concatenate(point_distribution.y))
175
+ z_list.append(np.concatenate(point_distribution.z))
176
+ sld_list.append(np.concatenate(point_distribution.sld))
177
+
178
+ ### read concentration, interface roughness/fuzziness, structure factor and structure factor-related parameters for model i
179
+ conc = check_input(args.conc, 0.02, "concentration", i)
180
+ sigma_r = check_input(args.sigma_r, 0.0, "sigma_r", i)
181
+ S_type = check_input(args.S, 'None', "Structure type", i)
182
+ stype = S_type.lower().replace("_", "").replace(" ", "")
183
+ try:
184
+ S_par = args.S_par[i][0]
185
+ except:
186
+ S_par = []
187
+
188
+ ### calculate p(r)
189
+ printt("\n Calculating pair distance distribution, p(r)...")
190
+ polydispersity = check_input(args.polydispersity, 0.0, "polydispersity", i)
191
+ r, pr, pr_norm, dmax = calc_pr_func(point_distribution,prpoints=args.prpoints, polydispersity=polydispersity)
192
+ save_pr_func(r,pr_norm,model_filename)
193
+ r_list.append(r)
194
+ pr_norm_list.append(pr_norm)
195
+
196
+ ### define q (and if sesans is opted for, also define the spin echo length, delta)
197
+ if args.sesans:
198
+ # make extended q-range for sesans
199
+ # the structure factor decides the length scale: an aggregate is
200
+ # larger than the particle it is built from
201
+ qmin, deltamax = getStructureFactorClass(stype).getSesansRange(S_par, dmax)
202
+ qmax = 1e4 * qmin
203
+ qpoints = 5000
204
+ q = np.linspace(qmin,qmax,qpoints)
205
+ delta = np.linspace(0, deltamax, args.deltapoints)
206
+ elif args.data:
207
+ header,footer = get_header_footer(args.data) # replace with function
208
+ q,I_exp,sigma_exp = np.genfromtxt(args.data,skip_header=header,skip_footer=footer,usecols=[0,1,2],unpack=True)
209
+ else:
210
+ q = np.linspace(args.qmin,args.qmax,args.qpoints)
211
+
212
+ printt("\n Calculating intensity, I(q)...")
213
+
214
+ ### calculate form factor and forward scattering I0
215
+ I0, Pq = calc_Pq_func(q, r, pr_norm, conc, point_distribution.volume_total)
216
+
217
+ ### calculate structure factor
218
+ S = calc_S_func(q,point_distribution, stype, S_par, Pq)
219
+ save_S_func(q,S,model_filename)
220
+ S_list.append(S)
221
+
222
+ ### calculate theoretical SAS (and SESANS)
223
+ I = calc_Iq_func(q, Pq, S, sigma_r)
224
+ save_I_func(q,I,model_filename)
225
+ I_list.append(I)
226
+ if args.sesans:
227
+ # calculated theoretical SESANS
228
+ G = calc_G_sesans(q,delta,I)
229
+ delta_list.append(delta)
230
+ G_list.append(G)
231
+
232
+ ### simulate SAXS (and SESANS)
233
+ I_sim,sigma = simulate_data_func(q,I,I0,args.exposure)
234
+ save_Isim_func(q,I_sim,sigma,model_filename)
235
+ I_sim_list.append(I_sim)
236
+ sigma_list.append(sigma)
237
+ if args.sesans:
238
+ # simulate sesans data
239
+ G_sim,sigma_G = simulate_sesans(delta,G,args.sesans_error)
240
+ # append to list (in case of multiple models)
241
+ G_sim_list.append(G_sim)
242
+ sigma_G_list.append(sigma_G)
243
+
244
+ printt(" ")
245
+ printt("Generating plots")
246
+ colors = ['blue','red','green','orange','purple','cyan','magenta','black','grey','pink','forestgreen','gold','darkred','coral','peru','olive','springgreen','teal','skyblue','navy','lavender','blueviolet','deeppink']
247
+
248
+ if args.high_res:
249
+ filetype = 'pdf'
250
+ else:
251
+ filetype = 'png'
252
+
253
+ # plot 2D projections
254
+ for m in model_filename_list:
255
+ print(" 2D projection: points_" + m + "." + filetype)
256
+ plot_2D(x_list, y_list, z_list, sld_list, model_filename_list, filetype, colors)
257
+
258
+ # 3D vizualization: generate pdb file with points
259
+ for m in model_filename_list:
260
+ print(" 3D models: " + m + ".pdb")
261
+ generate_pdb(x_list, y_list, z_list, sld_list, model_filename_list)
262
+
263
+ # plot p(r) and I(q)
264
+ print(" pr, Iq, and Isim: plot." + filetype)
265
+ plot_results(q, r_list, pr_norm_list, I_list, I_sim_list, sigma_list, S_list, model_name_list, args.xscale_lin, filetype, colors)
266
+
267
+ # plot fit
268
+ if args.data:
269
+ data_filename = args.data.split('/')[-1]
270
+ print(" fit(s) to exp data : fit." + filetype)
271
+ plot_fit(q, I_list, I_exp, sigma_exp, model_name_list, data_filename, args.xscale_lin, filetype, colors)
272
+
273
+ # plot and save sesans
274
+ if args.sesans:
275
+ print(" SESANS G and Gsim : sesans." + filetype)
276
+ plot_sesans(delta_list, G_list, G_sim_list, sigma_G_list, model_name_list, filetype, colors)
277
+ save_sesans(delta_list, G_list, G_sim_list, sigma_G_list, model_filename_list)
278
+
279
+ time_total = time.time() - start_total
280
+ printt(" ")
281
+ printt("Simulation successfully completed.")
282
+ printt(" Total run time: " + str(round(time_total, 1)) + " seconds.")
283
+ printt(" ")
284
+
285
+ # close log file and copy into model directories
286
+ #f_out.close()
287
+ extension = '.' + filetype
288
+ for model_filename in model_filename_list:
289
+ shutil.copy('shape2sas.log', model_filename + '/' + model_filename + '.log' )
290
+ shutil.copy('plot' + extension, model_filename + '/plot_' + model_filename + extension)
291
+ if args.data:
292
+ shutil.copy('fit' + extension, model_filename + '/fit_' + model_filename + '_' + data_filename + extension)
293
+ if args.sesans:
294
+ shutil.copy('sesans' + extension, model_filename + '/sesans_' + model_filename + extension )
295
+
296
+
297
+ if __name__ == "__main__":
298
+ main()
shape2sas/compare.py ADDED
@@ -0,0 +1,222 @@
1
+ import argparse
2
+ import re
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+
6
+
7
+ def main(argv=None):
8
+ """Entry point for the ``shape2sas-compare`` command."""
9
+
10
+ # input arguments
11
+ parser = argparse.ArgumentParser(description='Compare results from Shape2SAS')
12
+ parser.add_argument('-m', '--model_names',help='Model names')
13
+ parser.add_argument('-lin', '--xscale_lin', action='store_true', default=False,
14
+ help='include flag (no input) to make q scale linear instead of logarithmic.')
15
+ parser.add_argument('-hres', '--high_res', action='store_true', default=False,
16
+ help='include flag (no input) to output high resolution plot.')
17
+ parser.add_argument('-s', '--scale', action='store_true', default=False,
18
+ help='include flag (no input) to scale the simulated intensity of each model in the plots to avoid overlap')
19
+ parser.add_argument('-n', '--name', help='output filename', default='None')
20
+ parser.add_argument('-g', '--grid',action='store_true',help='add grid in 2D point representation',default=False)
21
+ parser.add_argument('-norm', '--normalization',help='normalization method: max, I0 (default) or none ',default='max')
22
+ parser.add_argument('-ss', '--sesans', action='store_true',help='plot SESANS data',default=False)
23
+ parser.add_argument('-p', '--plot_points', action='store_true',help='plot point distribution data',default=False)
24
+
25
+ args = parser.parse_args(argv)
26
+
27
+ # colors and models
28
+ colors = ['blue','red','green','orange','purple','cyan','magenta','black','grey','pink','forrestgreen']
29
+ models = re.split('[ ,]+', args.model_names)
30
+
31
+ # resolution
32
+ if args.high_res:
33
+ format = '.pdf'
34
+ else:
35
+ format ='.png'
36
+
37
+ ### plot SAS data: p(r), I(q), Isim(q)
38
+ fig, ax = plt.subplots(1,3,figsize=(12,4))
39
+ scale_factor = 1
40
+ zo=1
41
+ all_model_names = ''
42
+ for i,model in enumerate(models):
43
+ pr_filename = model + '/pr_' + model + '.dat'
44
+ r,pr = np.genfromtxt(pr_filename,skip_header=1,unpack=True)
45
+ if args.normalization in ['I0','Forward_Scattering','I0','I(0)','integral']:
46
+ dr = r[4]-r[3]
47
+ pr /= pr.sum()*dr
48
+ elif args.normalization in ['max','Max','pr_max','prmax']:
49
+ pr /= np.max(pr)
50
+ elif args.normalization in ['none','no','None','No']:
51
+ pass
52
+ else:
53
+ print('\n\nERROR: unknown normalization argument: ' + args.normalization + '. Should be "max" or "I0" or "none".\n\n')
54
+ exit()
55
+ ax[0].plot(r,pr,color=colors[i],label=model)
56
+
57
+ Iq_filename = model + '/Iq_' + model + '.dat'
58
+ q,I = np.genfromtxt(Iq_filename,skip_header=2,unpack=True)
59
+ ax[1].plot(q,I,color=colors[i],label=model)
60
+
61
+ Isim_filename = model + '/Isim_' + model + '.dat'
62
+ q,Isim,sigma = np.genfromtxt(Isim_filename,skip_header=3,unpack=True)
63
+ if args.scale:
64
+ ax[2].errorbar(q,Isim*scale_factor,yerr=sigma*scale_factor,linestyle='none',marker='.', color=colors[i],label=r'$I_\mathrm{sim}(q)$, %s, scaled by %1.0e' % (model,scale_factor),zorder=1/zo)
65
+ scale_factor *= 0.1
66
+ else:
67
+ ax[2].errorbar(q,Isim,yerr=sigma,linestyle='none',marker='.', color=colors[i],label=r'$I_\mathrm{sim}(q)$, %s' % model,zorder=zo)
68
+ if i > 0:
69
+ all_model_names += '_'
70
+ all_model_names += model
71
+
72
+ ax[0].set_xlabel(r'$r$ [$\mathrm{\AA}$]')
73
+ ax[0].set_ylabel(r'$p(r)$')
74
+ ax[0].set_title('pair distance distribution function')
75
+ ax[0].legend(frameon=False)
76
+
77
+ if not args.xscale_lin:
78
+ ax[1].set_xscale('log')
79
+ ax[1].set_yscale('log')
80
+ ax[1].set_xlabel(r'$q$ [$\mathrm{\AA}^{-1}$]')
81
+ ax[1].set_ylabel(r'normalized $I(q)$')
82
+ ax[1].set_title('normalized scattering, no noise')
83
+ ax[1].legend(frameon=False)
84
+
85
+ if not args.xscale_lin:
86
+ ax[2].set_xscale('log')
87
+ ax[2].set_yscale('log')
88
+ ax[2].set_xlabel(r'$q$ [$\mathrm{\AA}^{-1}$]')
89
+ ax[2].set_ylabel(r'$I(q)$ [a.u.]')
90
+ ax[2].set_title('simulated scattering, with noise')
91
+ ax[2].legend(frameon=True)
92
+
93
+ plt.tight_layout()
94
+ if args.name == 'None':
95
+ plt.savefig(all_model_names + '_compare' + format)
96
+ else:
97
+ plt.savefig(args.name + '_compare' + format)
98
+
99
+
100
+ ### plot points: 2D projection - if opted for
101
+ if args.plot_points:
102
+ n_models = len(models)
103
+ if n_models < 4:
104
+ fig, ax = plt.subplots(len(models),3,figsize=(9,3*len(models)))
105
+ elif n_models < 8:
106
+ fig, ax = plt.subplots(len(models),3,figsize=(6,2*len(models)))
107
+ else:
108
+ fig, ax = plt.subplots(len(models),3,figsize=(3,1*len(models)))
109
+ markersize = 0.5
110
+
111
+ # find max dimension
112
+ max_l = 0
113
+ for i,model in enumerate(models):
114
+ points_filename = model + '/points_' + model + '.txt'
115
+ x,y,z,sld = np.genfromtxt(points_filename,skip_header=1,unpack=True)
116
+ if np.amax(abs(x)) > max_l:
117
+ max_l = np.amax(abs(x))
118
+ if np.amax(abs(y)) > max_l:
119
+ max_l = np.amax(abs(y))
120
+ if np.amax(abs(z)) > max_l:
121
+ max_l = np.amax(abs(z))
122
+ max_l *= 1.1
123
+
124
+ lim = [-max_l, max_l]
125
+
126
+ for i,model in enumerate(models):
127
+
128
+ points_filename = model + '/points_' + model + '.txt'
129
+ x,y,z,sld = np.genfromtxt(points_filename,skip_header=1,unpack=True)
130
+
131
+ ## find indices of positive, zero and negatative contrast
132
+ idx_neg = np.where(sld < 0.0)
133
+ idx_pos = np.where(sld > 0.0)
134
+ idx_nul = np.where(sld == 0.0)
135
+
136
+ ## plot, perspective 1
137
+ ax[i,0].plot(x[idx_pos], z[idx_pos], linestyle='none', marker='.', markersize=markersize, color=colors[i])
138
+ ax[i,0].plot(x[idx_neg], z[idx_neg], linestyle='none', marker='.', markersize=markersize, color='black')
139
+ ax[i,0].plot(x[idx_nul], z[idx_nul], linestyle='none', marker='.', markersize=markersize, color='grey')
140
+ ax[i,0].set_xlim(lim)
141
+ ax[i,0].set_ylim(lim)
142
+ ax[i,0].set_xlabel('x')
143
+ ax[i,0].set_ylabel('z')
144
+ if i == 0:
145
+ ax[i,0].set_title('pointmodel, (x,z), "front"')
146
+ if args.grid:
147
+ ax[i,0].grid()
148
+
149
+ ## plot, perspective 2
150
+ ax[i,1].plot(y[idx_pos], z[idx_pos], linestyle='none', marker='.', markersize=markersize, color=colors[i])
151
+ ax[i,1].plot(y[idx_neg], z[idx_neg], linestyle='none', marker='.', markersize=markersize, color='black')
152
+ ax[i,1].plot(y[idx_nul], z[idx_nul], linestyle='none', marker='.', markersize=markersize, color='grey')
153
+ ax[i,1].set_xlim(lim)
154
+ ax[i,1].set_ylim(lim)
155
+ ax[i,1].set_xlabel('y')
156
+ ax[i,1].set_ylabel('z')
157
+ if i == 0:
158
+ ax[i,1].set_title('pointmodel, (y,z), "side"')
159
+ if args.grid:
160
+ ax[i,1].grid()
161
+
162
+ ## plot, perspective 3
163
+ ax[i,2].plot(x[idx_pos], y[idx_pos], linestyle='none', marker='.', markersize=markersize, color=colors[i])
164
+ ax[i,2].plot(x[idx_neg], y[idx_neg], linestyle='none', marker='.', markersize=markersize, color='black')
165
+ ax[i,2].plot(x[idx_nul], y[idx_nul], linestyle='none', marker='.', markersize=markersize, color='grey')
166
+ ax[i,2].set_xlim(lim)
167
+ ax[i,2].set_ylim(lim)
168
+ ax[i,2].set_xlabel('x')
169
+ ax[i,2].set_ylabel('y')
170
+ if i == 0:
171
+ ax[i,2].set_title('pointmodel, (x,y), "bottom"')
172
+ if args.grid:
173
+ ax[i,2].grid()
174
+
175
+ plt.tight_layout()
176
+ if args.name == 'None':
177
+ plt.savefig(all_model_names + '_compare_points' + format)
178
+ else:
179
+ plt.savefig(args.name + '_compare_points' + format)
180
+
181
+ ### plot sesans data, G(delta), G_sim(delta) - if opted for
182
+ if args.sesans:
183
+
184
+ fig, ax = plt.subplots(1,2,figsize=(8,4))
185
+ scale_factor = 1
186
+ for i,model in enumerate(models):
187
+ G_filename = model + '/G_' + model + '.ses'
188
+ d,G = np.genfromtxt(G_filename,skip_header=2,unpack=True)
189
+ ax[0].plot(d,G,color=colors[i],label=model)
190
+
191
+ ax[0].set_ylabel(r'$G(\delta)$ [cm$^{-1}$]')
192
+ ax[0].set_xlabel(r'$\delta$ [$\mathrm{\AA}$]')
193
+ ax[0].set_title('theoretical SESANS, no noise')
194
+ ax[0].legend(frameon=False)
195
+
196
+ Gsim_filename = model + '/Gsim_' + model + '.ses'
197
+ d,Gsim,sigmaG = np.genfromtxt(Gsim_filename,skip_header=2,unpack=True)
198
+ if args.scale:
199
+ ax[1].errorbar(d,Gsim*scale_factor,yerr=sigmaG*scale_factor,linestyle='none',marker='.', color=colors[i],label=r'$I_\mathrm{sim}(q)$, %s, scaled by %1.0e' % (model,scale_factor),zorder=1/zo)
200
+ scale_factor *= 0.1
201
+ else:
202
+ ax[1].errorbar(d,Gsim,yerr=sigmaG,linestyle='none',marker='.', color=colors[i],label=r'$I_\mathrm{sim}(q)$, %s' % model,zorder=zo)
203
+ if i > 0:
204
+ all_model_names += '_'
205
+ all_model_names += model
206
+
207
+ ax[1].set_xlabel(r'$\delta$ [$\mathrm{\AA}$]')
208
+ ax[1].set_ylabel(r'$\ln(P)/(t\lambda^2)$ [$\mathrm{\AA}^{-2}$cm$^{-1}$]')
209
+ ax[1].set_title('simulated SESANS, with noise')
210
+ ax[1].legend(frameon=True)
211
+
212
+ plt.tight_layout()
213
+ if args.name == 'None':
214
+ plt.savefig(all_model_names + '_sesans' + format)
215
+ else:
216
+ plt.savefig(args.name + '_sesans' + format)
217
+
218
+ plt.show()
219
+
220
+
221
+ if __name__ == "__main__":
222
+ main()