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, median, zeros
28 from time import asctime, localtime
29
30
31 from lib.errors import RelaxError
32 from lib.io import open_write_file
33 from extern.numpy_future import percentile
34 from lib.software.opendx.files import write_config, write_general, write_point, write_program
35 from pipe_control import value
36 from specific_analyses.api import return_api
37
38 -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", chi_surface=None):
39 """Map the space corresponding to the spin identifier and create the OpenDX files.
40
41 @keyword params:
42 @type params:
43 @keyword map_type: The type of map to create. The available options are:
44 - 'Iso3D', a 3D isosurface visualisation of the space.
45 @type map_type: str
46 @keyword spin_id: The spin identification string.
47 @type spin_id: str
48 @keyword inc: The resolution of the plot. This is the number of increments per
49 dimension.
50 @type inc: int
51 @keyword lower: The lower bounds of the space to map. If supplied, this should be a
52 list of floats, its length equal to the number of parameters in the
53 model.
54 @type lower: None or list of float
55 @keyword upper: The upper bounds of the space to map. If supplied, this should be a
56 list of floats, its length equal to the number of parameters in the
57 model.
58 @type upper: None or list of float
59 @keyword axis_incs: The number of tick marks to display in the OpenDX plot in each
60 dimension.
61 @type axis_incs: int
62 @keyword file_prefix: The file prefix for all the created files.
63 @type file_prefix: str
64 @keyword dir: The directory to place the files into.
65 @type dir: str or None
66 @keyword point: If supplied, a red sphere will be placed at these coordinates.
67 @type point: None or list of float
68 @keyword point_file: The file prefix for the point output files.
69 @type point_file: str or None
70 """
71
72
73 if inc <= 1:
74 raise RelaxError("The increment value needs to be greater than 1.")
75 if axis_incs <= 1:
76 raise RelaxError("The axis increment value needs to be greater than 1.")
77
78
79 if map_type.lower() == "iso3d":
80 if len(params) != 3:
81 raise RelaxError("The 3D isosurface map requires a 3 parameter model.")
82
83
84 Map(params, spin_id, inc, lower, upper, axis_incs, file_prefix, dir, point, point_file, chi_surface)
85 else:
86 raise RelaxError("The map type '" + map_type + "' is not supported.")
87
88
89
91 """The space mapping base class."""
92
93 - def __init__(self, params, spin_id, inc, lower, upper, axis_incs, file_prefix, dir, point, point_file, chi_surface):
94 """Map the space upon class instantiation."""
95
96
97
98
99
100 self.params = params
101 self.spin_id = spin_id
102 self.n = len(params)
103 self.inc = inc
104 self.axis_incs = axis_incs
105 self.file_prefix = file_prefix
106 self.dir = dir
107 self.point_file = point_file
108
109
110 self.api = return_api()
111
112
113 if point != None:
114
115 if isinstance(point[0], float):
116 self.point = array(point, float64)
117 self.num_points = 1
118 else:
119 point_list = []
120 for i in range(len(point)):
121 point_list.append(array(point[i], float64))
122 self.point = point_list
123 self.num_points = i + 1
124 else:
125 self.num_points = 0
126
127
128 self.bounds = zeros((self.n, 2), float64)
129 for i in range(self.n):
130
131 bounds = self.api.map_bounds(self.params[i], self.spin_id)
132
133
134 if not bounds:
135 raise RelaxError("No bounds for the parameter " + repr(self.params[i]) + " could be determined.")
136
137
138 self.bounds[i] = bounds
139
140
141 if lower != None:
142 self.bounds[:, 0] = array(lower, float64)
143
144
145 if upper != None:
146 self.bounds[:, 1] = array(upper, float64)
147
148
149 self.step_size = zeros(self.n, float64)
150 self.step_size = (self.bounds[:, 1] - self.bounds[:, 0]) / self.inc
151
152
153
154
155
156
157 self.get_date()
158
159
160 self.map_axes()
161
162
163 self.create_map()
164
165
166 if chi_surface == None:
167 all_chi2 = array(self.all_chi, float64)
168 innermost = percentile(all_chi2, 10)
169 inner = percentile(all_chi2, 20)
170 middle = percentile(all_chi2, 50)
171 outer = percentile(all_chi2, 90)
172 chi_surface = [innermost, inner, middle, outer]
173
174
175 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, chi_surface = chi_surface)
176
177
178 write_config(file_prefix=self.file_prefix, dir=self.dir, date=self.date)
179
180
181 write_general(file_prefix=self.file_prefix, dir=self.dir, inc=self.inc)
182
183
184 if self.num_points > 1:
185 write_point(file_prefix=self.point_file, dir=self.dir, inc=self.inc, point=self.point, num_points=self.num_points, bounds=self.bounds, N=self.n)
186
187
189 """Function for creating the map."""
190
191
192 print("\nCreating the map.")
193
194
195 map_file = open_write_file(file_name=self.file_prefix, dir=self.dir, force=True)
196
197
198 self.map_3D_text(map_file)
199
200
201 map_file.close()
202
203
205 """Function for creating a date string."""
206
207 self.date = asctime(localtime())
208
209
210 - def map_3D_text(self, map_file):
211 """Function for creating the text of a 3D map."""
212
213
214 values = zeros(3, float64)
215 percent = 0.0
216 percent_inc = 100.0 / (self.inc + 1.0)**(self.n - 1.0)
217 print("%-10s%8.3f%-1s" % ("Progress:", percent, "%"))
218
219
220 all_chi = []
221
222
223 unfix = False
224 if hasattr(cdp, 'diff_tensor') and not cdp.diff_tensor.fixed:
225 cdp.diff_tensor.fixed = True
226 unfix = True
227
228
229 values[0] = self.bounds[0, 0]
230
231
232 for i in range((self.inc + 1)):
233
234 values[1] = self.bounds[1, 0]
235
236
237 for j in range((self.inc + 1)):
238
239 values[2] = self.bounds[2, 0]
240
241
242 for k in range((self.inc + 1)):
243
244 if self.spin_id:
245 value.set(val=values, param=self.params, spin_id=self.spin_id, force=True)
246 else:
247 value.set(val=values, param=self.params, force=True)
248
249
250 if self.spin_id:
251 self.api.calculate(spin_id=self.spin_id, verbosity=0)
252 else:
253 self.api.calculate(verbosity=0)
254
255
256 if self.spin_id:
257 k, n, chi2 = self.api.model_statistics(spin_id=self.spin_id)
258 else:
259 k, n, chi2 = self.api.model_statistics(model_info=0)
260
261
262 if chi2 > 1e20:
263 map_file.write("%30f\n" % 1e20)
264 else:
265 map_file.write("%30f\n" % chi2)
266
267
268 all_chi.append(chi2)
269
270
271 values[2] = values[2] + self.step_size[2]
272
273
274 percent = percent + percent_inc
275 print("%-10s%8.3f%-8s%-8g" % ("Progress:", percent, "%, " + repr(values) + ", f(x): ", chi2))
276
277
278 values[1] = values[1] + self.step_size[1]
279
280
281 values[0] = values[0] + self.step_size[0]
282
283
284 if unfix:
285 cdp.diff_tensor.fixed = False
286
287
288 self.all_chi = all_chi
289
291 """Function for creating labels, tick locations, and tick values for an OpenDX map."""
292
293
294 self.labels = "{"
295 self.tick_locations = []
296 self.tick_values = []
297 loc_inc = float(self.inc) / float(self.axis_incs)
298
299
300 for i in range(self.n):
301
302 factor = self.api.return_conversion_factor(self.params[i])
303
304
305 units = self.api.return_units(self.params[i])
306
307
308 if units:
309 self.labels = self.labels + "\"" + self.params[i] + " (" + units + ")\""
310 else:
311 self.labels = self.labels + "\"" + self.params[i] + "\""
312
313 if i < self.n - 1:
314 self.labels = self.labels + " "
315 else:
316 self.labels = self.labels + "}"
317
318
319 vals = self.bounds[i, 0] / factor
320 val_inc = (self.bounds[i, 1] - self.bounds[i, 0]) / (self.axis_incs * factor)
321
322 string = ""
323 for j in range(self.axis_incs + 1):
324 string = string + "\"" + "%.2f" % vals + "\" "
325 vals = vals + val_inc
326 self.tick_values.append("{" + string + "}")
327
328
329 string = ""
330 val = 0.0
331 for j in range(self.axis_incs + 1):
332 string = string + " " + repr(val)
333 val = val + loc_inc
334 self.tick_locations.append("{" + string + " }")
335