1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module containing the base class for the OpenDX space mapping classes."""
24
25
26
27 from numpy import float64, array, zeros
28 from time import asctime, localtime
29
30
31 from lib.errors import RelaxError, RelaxUnknownParamError
32 from lib.io import open_write_file
33 from lib.software.opendx.files import write_config, write_general, write_point, write_program
34 from pipe_control import diffusion_tensor
35 from pipe_control import pipes
36 from pipe_control import value
37 from specific_analyses.setup import get_specific_fn
38
39
40 -def map(params=None, map_type='Iso3D', spin_id=None, inc=20, lower=None, upper=None, axis_incs=10, file_prefix="map", dir="dx", point=None, point_file="point", remap=None):
41 """Map the space corresponding to the spin identifier and create the OpenDX files.
42
43 @keyword params:
44 @type params:
45 @keyword map_type: The type of map to create. The available options are:
46 - 'Iso3D', a 3D isosurface visualisation of the space.
47 @type map_type: str
48 @keyword spin_id: The spin identification string.
49 @type spin_id: str
50 @keyword inc: The resolution of the plot. This is the number of increments per
51 dimension.
52 @type inc: int
53 @keyword lower: The lower bounds of the space to map. If supplied, this should be a
54 list of floats, its length equal to the number of parameters in the
55 model.
56 @type lower: None or list of float
57 @keyword upper: The upper bounds of the space to map. If supplied, this should be a
58 list of floats, its length equal to the number of parameters in the
59 model.
60 @type upper: None or list of float
61 @keyword axis_incs: The number of tick marks to display in the OpenDX plot in each
62 dimension.
63 @type axis_incs: int
64 @keyword file_prefix: The file prefix for all the created files.
65 @type file_prefix: str
66 @keyword dir: The directory to place the files into.
67 @type dir: str or None
68 @keyword point: If supplied, a red sphere will be placed at these coordinates.
69 @type point: None or list of float
70 @keyword point_file: The file prefix for the point output files.
71 @type point_file: str or None
72 @keyword remap: A function which is used to remap the space. The function should accept
73 the parameter array (list of float) and return an array of equal length
74 (again list of float).
75 @type remap: None or func
76 """
77
78
79 if inc <= 1:
80 raise RelaxError("The increment value needs to be greater than 1.")
81 if axis_incs <= 1:
82 raise RelaxError("The axis increment value needs to be greater than 1.")
83
84
85 if map_type.lower() == "iso3d":
86 if len(params) != 3:
87 raise RelaxError("The 3D isosurface map requires a 3 parameter model.")
88
89
90 Map(params, spin_id, inc, lower, upper, axis_incs, file_prefix, dir, point, point_file, remap)
91 else:
92 raise RelaxError("The map type '" + map_type + "' is not supported.")
93
94
95
97 """The space mapping base class."""
98
99 - def __init__(self, params, spin_id, inc, lower, upper, axis_incs, file_prefix, dir, point, point_file, remap):
100 """Map the space upon class instantiation."""
101
102
103
104
105
106 self.params = params
107 self.spin_id = spin_id
108 self.n = len(params)
109 self.inc = inc
110 self.axis_incs = axis_incs
111 self.file_prefix = file_prefix
112 self.dir = dir
113 self.point_file = point_file
114 self.remap = remap
115
116
117 self.calculate = get_specific_fn('calculate', cdp.pipe_type)
118 self.model_stats = get_specific_fn('model_stats', cdp.pipe_type)
119 self.return_data_name = get_specific_fn('return_data_name', cdp.pipe_type)
120 self.map_bounds = []
121 self.return_conversion_factor = []
122 self.return_units = []
123 for i in range(self.n):
124 self.map_bounds.append(get_specific_fn('map_bounds', cdp.pipe_type))
125 self.return_conversion_factor.append(get_specific_fn('return_conversion_factor', cdp.pipe_type))
126 self.return_units.append(get_specific_fn('return_units', cdp.pipe_type))
127
128
129 self.diff_params = zeros(self.n)
130
131
132 self.get_param_names()
133
134
135 for i in range(self.n):
136 if self.diff_params[i]:
137 self.map_bounds[i] = diffusion_tensor.map_bounds
138 self.return_conversion_factor[i] = diffusion_tensor.return_conversion_factor
139 self.return_units[i] = diffusion_tensor.return_units
140
141
142 if point != None:
143 self.point = array(point, float64)
144 self.num_points = 1
145 else:
146 self.num_points = 0
147
148
149 self.bounds = zeros((self.n, 2), float64)
150 for i in range(self.n):
151
152 bounds = self.map_bounds[i](self.param_names[i], self.spin_id)
153
154
155 if not bounds:
156 raise RelaxError("No bounds for the parameter " + repr(self.params[i]) + " could be determined.")
157
158
159 self.bounds[i] = bounds
160
161
162 if lower != None:
163 self.bounds[:, 0] = array(lower, float64)
164
165
166 if upper != None:
167 self.bounds[:, 1] = array(upper, float64)
168
169
170 self.step_size = zeros(self.n, float64)
171 self.step_size = (self.bounds[:, 1] - self.bounds[:, 0]) / self.inc
172
173
174
175
176
177
178 self.get_date()
179
180
181 self.map_axes()
182
183
184 write_program(file_prefix=self.file_prefix, point_file=self.point_file, dir=self.dir, inc=self.inc, N=self.n, num_points=self.num_points, labels=self.labels, tick_locations=self.tick_locations, tick_values=self.tick_values, date=self.date)
185
186
187 write_config(file_prefix=self.file_prefix, dir=self.dir, date=self.date)
188
189
190 write_general(file_prefix=self.file_prefix, dir=self.dir, inc=self.inc)
191
192
193 if self.num_points == 1:
194 write_point(file_prefix=self.point_file, dir=self.dir, inc=self.inc, point=self.point, bounds=self.bounds, N=self.n)
195
196
197 self.create_map()
198
199
201 """Function for creating the map."""
202
203
204 print("\nCreating the map.")
205
206
207 map_file = open_write_file(file_name=self.file_prefix, dir=self.dir, force=True)
208
209
210 self.map_3D_text(map_file)
211
212
213 map_file.close()
214
215
217 """Function for creating a date string."""
218
219 self.date = asctime(localtime())
220
221
251
252
253 - def map_3D_text(self, map_file):
254 """Function for creating the text of a 3D map."""
255
256
257 values = zeros(3, float64)
258 percent = 0.0
259 percent_inc = 100.0 / (self.inc + 1.0)**(self.n - 1.0)
260 print("%-10s%8.3f%-1s" % ("Progress:", percent, "%"))
261
262
263 unfix = False
264 if hasattr(cdp, 'diff_tensor') and not cdp.diff_tensor.fixed:
265 cdp.diff_tensor.fixed = True
266 unfix = True
267
268
269 values[0] = self.bounds[0, 0]
270
271
272
273
274 for i in range((self.inc + 1)):
275
276 values[1] = self.bounds[1, 0]
277
278
279 for j in range((self.inc + 1)):
280
281 values[2] = self.bounds[2, 0]
282
283
284 for k in range((self.inc + 1)):
285
286 if self.spin_id:
287 value.set(val=values, param=self.params, spin_id=self.spin_id, force=True)
288 else:
289 value.set(val=values, param=self.params, force=True)
290
291
292 if self.spin_id:
293 self.calculate(spin_id=self.spin_id, verbosity=0)
294 else:
295 self.calculate(verbosity=0)
296
297
298 if self.spin_id:
299 k, n, chi2 = self.model_stats(spin_id=self.spin_id)
300 else:
301 k, n, chi2 = self.model_stats(model_info=0)
302
303
304 if chi2 > 1e20:
305 map_file.write("%30f\n" % 1e20)
306 else:
307 map_file.write("%30f\n" % chi2)
308
309
310 values[2] = values[2] + self.step_size[2]
311
312
313 percent = percent + percent_inc
314 print("%-10s%8.3f%-8s%-8g" % ("Progress:", percent, "%, " + repr(values) + ", f(x): ", chi2))
315
316
317 values[1] = values[1] + self.step_size[1]
318
319
320 values[0] = values[0] + self.step_size[0]
321
322
323 if unfix:
324 cdp.diff_tensor.fixed = False
325
326
328 """Function for creating labels, tick locations, and tick values for an OpenDX map."""
329
330
331 self.labels = "{"
332 self.tick_locations = []
333 self.tick_values = []
334 loc_inc = float(self.inc) / float(self.axis_incs)
335
336
337 for i in range(self.n):
338
339 factor = self.return_conversion_factor[i](self.param_names[i])
340
341
342 units = self.return_units[i](self.param_names[i])
343
344
345 if units:
346 self.labels = self.labels + "\"" + self.params[i] + " (" + units + ")\""
347 else:
348 self.labels = self.labels + "\"" + self.params[i] + "\""
349
350 if i < self.n - 1:
351 self.labels = self.labels + " "
352 else:
353 self.labels = self.labels + "}"
354
355
356 vals = self.bounds[i, 0] / factor
357 val_inc = (self.bounds[i, 1] - self.bounds[i, 0]) / (self.axis_incs * factor)
358
359 string = ""
360 for j in range(self.axis_incs + 1):
361 string = string + "\"" + "%.2f" % vals + "\" "
362 vals = vals + val_inc
363 self.tick_values.append("{" + string + "}")
364
365
366 string = ""
367 val = 0.0
368 for j in range(self.axis_incs + 1):
369 string = string + " " + repr(val)
370 val = val + loc_inc
371 self.tick_locations.append("{" + string + " }")
372