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.
- shape2sas/__init__.py +1 -0
- shape2sas/cli.py +298 -0
- shape2sas/compare.py +222 -0
- shape2sas/helpfunctions.py +180 -0
- shape2sas/mixture.py +193 -0
- shape2sas/models.py +210 -0
- shape2sas/plots.py +217 -0
- shape2sas/sesans/__init__.py +9 -0
- shape2sas/sesans/sesans_calculations.py +43 -0
- shape2sas/sesans/sesans_helpfunctions.py +7 -0
- shape2sas/sesans/sesans_output.py +59 -0
- shape2sas/simulated_scattering.py +72 -0
- shape2sas/structure_factors/Aggregation.py +44 -0
- shape2sas/structure_factors/HardSphere.py +82 -0
- shape2sas/structure_factors/NoStructure.py +23 -0
- shape2sas/structure_factors/__init__.py +21 -0
- shape2sas/structure_factors/structure_factors_helpfunctions.py +63 -0
- shape2sas/subunits/CircularDisc.py +8 -0
- shape2sas/subunits/Cube.py +31 -0
- shape2sas/subunits/Cuboid.py +28 -0
- shape2sas/subunits/Cylinder.py +39 -0
- shape2sas/subunits/CylinderRing.py +51 -0
- shape2sas/subunits/Disc.py +8 -0
- shape2sas/subunits/Ellipsoid.py +38 -0
- shape2sas/subunits/Ellipsoid_shell.py +39 -0
- shape2sas/subunits/EllipticalCylinder.py +37 -0
- shape2sas/subunits/HollowCube.py +75 -0
- shape2sas/subunits/HollowSphere.py +56 -0
- shape2sas/subunits/Hyperboloid.py +36 -0
- shape2sas/subunits/Sphere.py +37 -0
- shape2sas/subunits/Superellipsoid.py +43 -0
- shape2sas/subunits/Torus.py +38 -0
- shape2sas/subunits/__init__.py +21 -0
- shape2sas/subunits/subunits_helpfunctions.py +15 -0
- shape2sas/theoretical_scattering.py +250 -0
- shape2sas-0.0.1.dist-info/METADATA +521 -0
- shape2sas-0.0.1.dist-info/RECORD +41 -0
- shape2sas-0.0.1.dist-info/WHEEL +5 -0
- shape2sas-0.0.1.dist-info/entry_points.txt +4 -0
- shape2sas-0.0.1.dist-info/licenses/LICENSE +674 -0
- 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()
|