Changeset 61cada5 in sasview
- Timestamp:
- May 21, 2010 4:57:13 PM (15 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 26f3dd5
- Parents:
- 9e8c150
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sansview/perspectives/fitting/pagestate.py
r7609f1a r61cada5 1 import time, os, sys 2 import logging 3 import DataLoader 4 from xml.dom.minidom import parse 5 from lxml import etree 1 6 2 7 3 8 import copy 9 10 from DataLoader.readers.cansas_reader import Reader as CansasReader 11 from DataLoader.readers.cansas_reader import get_content 12 13 FITTING_NODE_NAME = 'fitting_plug_in' 14 CANSAS_NS = "cansas1d/1.0" 15 16 list_of_state_attributes = [["is_data", "is_data", "bool"], 17 ["group_id", "data_group_id", "string"], 18 ["data_name", "data_name", "string"], 19 ["data_id", "data_id", "string"], 20 ["name", "name", "string"], 21 ["data_name", "data_name", "string"], 22 ["qmin", "qmin", "float"], 23 ["qmax", "qmax", "float"], 24 ["npts", "npts", "float"], 25 ["shape_rbutton", "shape_rbutton", "bool"], 26 ["shape_indep_rbutton", "shape_indep_rbutton", "bool"], 27 ["plugin_rbutton", "plugin_rbutton","bool"], 28 ["struct_rbutton", "struct_rbutton", "bool"], 29 ["formfactorcombobox", "formfactorcombobox", "bool"], 30 ["structurecombobox", "structurecombobox", "bool"], 31 ["disp_box", "disp_box"]] 32 list_of_state_parameters = [["parameters", "parameters"] , 33 ["orientation_parameters", "orientation_params"], 34 ["dispersity_parameters", "orientation_params_disp"], 35 ["fixed_param", "fixed_param"], 36 ["fittable_param","fittable_param"]] 4 37 5 38 class PageState(object): 6 39 """ 7 Contains info to reconstruct a page40 Contains information to reconstruct a page of the fitpanel 8 41 """ 9 def __init__(self, parent ,model=None, data=None):42 def __init__(self, parent=None, model=None, data=None): 10 43 11 44 """ 12 Initialization of the Panel 13 """ 45 Initialize the current state 46 """ 47 self.file = None 14 48 #TODO: remove this once the inheritence is cleaned up 15 49 ## Data member to store the dispersion object created 16 50 self._disp_obj_dict = {} 51 #------------------------ 52 #Data used for fitting 53 self.data = data 54 #save additional information on data that dataloader.reader does not read 55 self.is_data = None 56 self.data_name = "" 57 58 if self.data is not None: 59 self.data_name = self.data.name 60 self.data_id = None 61 if self.data is not None and hasattr(self.data, "id"): 62 self.data_id = self.data.id 63 self.data_group_id = None 64 if self.data is not None and hasattr(self.data, "group_id"): 65 self.data_group_id = self.data.group_id 66 #------------------------- 17 67 ## reset True change the state of exsiting button 18 68 self.reset = False 19 #Data used for fitting 20 self.data = data 69 21 70 #engine type 22 71 self.engine_type = None … … 25 74 # model on which the fit would be performed 26 75 self.model = model 27 #if not hasattr(self.model, "_persistency_dict"): 28 # self.model._persistency_dict = {} 29 #self.model._persistency_dict = copy.deepcopy(model._persistency_dict) 76 30 77 #fit page manager 31 78 self.manager = None … … 38 85 self.page_name = "" 39 86 # Contains link between model ,all its parameters, and panel organization 40 self.parameters = []87 self.parameters = [] 41 88 # Contains list of parameters that cannot be fitted and reference to 42 89 #panel objects 43 self.fixed_param = []90 self.fixed_param = [] 44 91 # Contains list of parameters with dispersity and reference to 45 92 #panel objects 46 self.fittable_param = []93 self.fittable_param = [] 47 94 ## orientation parameters 48 self.orientation_params =[]95 self.orientation_params = [] 49 96 ## orientation parmaters for gaussian dispersity 50 self.orientation_params_disp =[]97 self.orientation_params_disp = [] 51 98 ## smearer info 52 self.smearer =None99 self.smearer = None 53 100 self.smear_type = None 54 101 self.dq_l = None … … 57 104 #list of dispersion paramaters 58 105 self.disp_list =[] 59 if self.model !=None:106 if self.model is not None: 60 107 self.disp_list = self.model.getDispParamList() 61 self._disp_obj_dict ={}62 self.disp_cb_dict ={}63 self.values =[]64 self.weights =[]108 self._disp_obj_dict = {} 109 self.disp_cb_dict = {} 110 self.values = [] 111 self.weights = [] 65 112 66 113 #contains link between a model and selected parameters to fit 67 self.param_toFit = []114 self.param_toFit = [] 68 115 ##dictionary of model type and model class 69 116 self.model_list_box = None 70 117 ## save the state of the context menu 71 self.saved_states ={}118 self.saved_states = {} 72 119 ## save selection of combobox 73 120 self.formfactorcombobox = None … … 82 129 ## Qrange 83 130 ## Q range 84 self.qmin = 0.00185 self.qmax = 0.1131 self.qmin = 0.001 132 self.qmax = 0.1 86 133 self.npts = None 87 self.name =""134 self.name = "" 88 135 ## enable smearering state 89 136 self.enable_smearer = False … … 92 139 self.slit_smearer = False 93 140 ## disperity selection 94 self.enable_disp = False95 self.disable_disp = True141 self.enable_disp = False 142 self.disable_disp = True 96 143 ## plot 2D data 97 self.enable2D = False144 self.enable2D = False 98 145 ## state of selected all check button 99 146 self.cb1 = False 100 147 ## store value of chisqr 101 self.tcChi = None148 self.tcChi = None 102 149 103 150 def clone(self): 104 model=None 105 if self.model !=None: 151 """ 152 Create a new copy of the current object 153 """ 154 model = None 155 if self.model is not None: 106 156 model = self.model.clone() 107 157 108 obj = PageState( self.parent,model= model ) 158 obj = PageState(self.parent, model=model) 159 obj.file = copy.deepcopy(self.file) 109 160 obj.data = copy.deepcopy(self.data) 161 if self.data is not None: 162 self.data_name = self.data.name 163 obj.data_name = self.data_name 164 obj.is_data = self.is_data 110 165 obj.model_list_box = copy.deepcopy(self.model_list_box) 111 166 obj.engine_type = copy.deepcopy(self.engine_type) 112 167 113 obj.formfactorcombobox = self.formfactorcombobox114 obj.structurecombobox = self.structurecombobox168 obj.formfactorcombobox = self.formfactorcombobox 169 obj.structurecombobox = self.structurecombobox 115 170 116 171 obj.shape_rbutton = self.shape_rbutton … … 150 205 obj.dq_r = copy.deepcopy(self.dq_r) 151 206 152 153 207 obj.disp_box = copy.deepcopy(self.disp_box) 154 208 obj.qmin = copy.deepcopy(self.qmin) … … 163 217 obj.saved_states[copy_name]= copy_state 164 218 return obj 165 166 167 def old__repr__(self): 168 """ output string for printing""" 169 rep = "\n\nState name: %s\n"%self.name 170 rep +="data : %s\n"% str(self.data) 171 rep += "Plotting Range: min: %s, max: %s, steps: %s\n"%(str(self.qmin), 172 str(self.qmax),str(self.npts)) 173 rep +="model : %s\n\n"% str(self.model) 174 rep +="number parameters(self.parameters): %s\n"%len(self.parameters) 175 for item in self.parameters: 219 220 def _repr_helper(self, list, rep): 221 """ 222 """ 223 for item in list: 176 224 rep += "parameter name: %s \n"%str(item[1]) 177 225 rep += "value: %s\n"%str(item[2]) … … 184 232 rep += "maximum value : %s \n"%str(item[6][1]) 185 233 rep += "parameter unit: %s\n\n"%str(item[7]) 186 rep +="number orientation parameters"187 rep +="(self.orientation_params): %s\n"%len(self.orientation_params)188 for item in self.orientation_params:189 rep += "parameter name: %s \n"%str(item[1])190 rep += "value: %s\n"%str(item[2])191 rep += "selected: %s\n"%str(item[0])192 rep += "error displayed : %s \n"%str(item[4][0])193 rep += "error value:%s \n"%str(item[4][1])194 rep += "minimum displayed : %s \n"%str(item[5][0])195 rep += "minimum value : %s \n"%str(item[5][1])196 rep += "maximum displayed : %s \n"%str(item[6][0])197 rep += "maximum value : %s \n"%str(item[6][1])198 rep += "parameter unit: %s\n\n"%str(item[7])199 rep +="number dispersity parameters"200 rep +="(self.orientation_params_disp): %s\n"%len(self.orientation_params_disp)201 for item in self.orientation_params_disp:202 rep += "parameter name: %s \n"%str(item[1])203 rep += "value: %s\n"%str(item[2])204 rep += "selected: %s\n"%str(item[0])205 rep += "error displayed : %s \n"%str(item[4][0])206 rep += "error value:%s \n"%str(item[4][1])207 rep += "minimum displayed : %s \n"%str(item[5][0])208 rep += "minimum value : %s \n"%str(item[5][1])209 rep += "maximum displayed : %s \n"%str(item[6][0])210 rep += "maximum value : %s \n"%str(item[6][1])211 rep += "parameter unit: %s\n\n"%str(item[7])212 213 234 return rep 214 215 235 236 def __repr__(self): 237 """ output string for printing""" 238 rep = "\n\nState name: %s\n"%self.name 239 rep += "\n\nState form factor combobox selection: %s\n"%self.formfactorcombobox 240 rep += "\n\nState structure factor combobox selection: %s\n"%self.structurecombobox 241 rep += "\n\n is data : %s\n"%self.is_data 242 rep += "\n\n data's name : %s\n"%self.data_name 243 rep += "\n\n data's id : %s\n"%self.data_id 244 rep += "\n\n model type (form factor) selected: %s\n"%self.shape_rbutton 245 rep += "\n\n model type (shape independent) selected: %s\n "%self.shape_indep_rbutton 246 rep += "\n\n model type (structure factor) selected: %s\n"%self.struct_rbutton 247 rep += "\n\n model type (plug-in ) selected: %s\n"%self.plugin_rbutton 248 #rep +="data : %s\n"% str(self.data) 249 #rep += "Plotting Range: min: %s, max: %s, steps: %s\n"%(str(self.qmin), 250 # str(self.qmax),str(self.npts)) 251 #rep +="model : %s\n\n"% str(self.model) 252 #rep +="number parameters(self.parameters): %s\n"%len(self.parameters) 253 #rep += self._repr_helper( list=self.parameters, rep=rep) 254 #rep +="number orientation parameters" 255 #rep +="(self.orientation_params): %s\n"%len(self.orientation_params) 256 #rep += self._repr_helper( list=self.orientation_params, rep=rep) 257 #rep +="number dispersity parameters" 258 #rep +="(self.orientation_params_disp): %s\n"%len(self.orientation_params_disp) 259 #rep += self._repr_helper( list=self.orientation_params_disp, rep=rep) 216 260 261 return rep 262 263 def _toXML_helper(self, list, element, newdoc): 264 """ 265 """ 266 for item in list: 267 sub_element = newdoc.createElement('parameter') 268 sub_element.setAttribute('name', str(item[1])) 269 sub_element.setAttribute('value', str(item[2])) 270 sub_element.setAttribute('selected_to_fit', str(item[0])) 271 sub_element.setAttribute('error_displayed', str(item[4][0])) 272 sub_element.setAttribute('error_value', str(item[4][1])) 273 sub_element.setAttribute('minimum_displayed', str(item[5][0])) 274 sub_element.setAttribute('minimum_value', str(item[5][1])) 275 sub_element.setAttribute('maximum_displayed', str(item[6][0])) 276 sub_element.setAttribute('maximum_value', str(item[6][1])) 277 sub_element.setAttribute('unit', str(item[7])) 278 element.appendChild(sub_element) 279 280 281 def toXML(self, file="fitting_state.fitv", doc=None, entry_node=None): 282 """ 283 Writes the state of the InversionControl panel to file, as XML. 284 285 Compatible with standalone writing, or appending to an 286 already existing XML document. In that case, the XML document 287 is required. An optional entry node in the XML document may also be given. 288 289 @param file: file to write to 290 @param doc: XML document object [optional] 291 @param entry_node: XML node within the XML document at which we will append the data [optional] 292 """ 293 from xml.dom.minidom import getDOMImplementation 294 295 # Check whether we have to write a standalone XML file 296 if doc is None: 297 impl = getDOMImplementation() 298 doc_type = impl.createDocumentType(FITTING_NODE_NAME, "1.0", "1.0") 299 newdoc = impl.createDocument(None, FITTING_NODE_NAME, doc_type) 300 top_element = newdoc.documentElement 301 else: 302 # We are appending to an existing document 303 newdoc = doc 304 top_element = newdoc.createElement(FITTING_NODE_NAME) 305 if entry_node is None: 306 newdoc.documentElement.appendChild(top_element) 307 else: 308 entry_node.appendChild(top_element) 309 310 attr = newdoc.createAttribute("version") 311 attr.nodeValue = '1.0' 312 top_element.setAttributeNode(attr) 313 314 # File name 315 element = newdoc.createElement("filename") 316 if self.file is not None: 317 element.appendChild(newdoc.createTextNode(str(self.file))) 318 else: 319 element.appendChild(newdoc.createTextNode(str(file))) 320 top_element.appendChild(element) 321 322 # Inputs 323 inputs = newdoc.createElement("Attributes") 324 top_element.appendChild(inputs) 217 325 326 element = newdoc.createElement('data_attributes') 327 if self.data is not None and hasattr(self.data, "group_id"): 328 self.data_group_id = self.data.group_id 329 if self.data is not None and hasattr(self.data, "is_data"): 330 self.is_data = self.data.is_data 331 if self.data is not None: 332 self.data_name = self.data.name 333 if self.data is not None and hasattr(self.data, "id"): 334 self.data_id = self.data.id 335 336 for item in list_of_state_attributes: 337 exec "element.setAttribute(item[0], str(self.%s))"%(item[1]) 338 inputs.appendChild(element) 339 340 for item in list_of_state_parameters: 341 element = newdoc.createElement(item[0]) 342 exec "self._toXML_helper(list=self.%s, element=element, newdoc=newdoc)"%item[1] 343 inputs.appendChild(element) 344 345 # Save the file 346 if doc is None: 347 fd = open(file, 'w') 348 fd.write(newdoc.toprettyxml()) 349 fd.close() 350 return None 351 else: 352 return newdoc.toprettyxml() 353 354 def _fromXML_helper(self, node, list): 355 """ 356 """ 357 for item in node: 358 name = item.get('name') 359 value = item.get('value') 360 selected_to_fit = item.get('selected_to_fit') 361 error_displayed = item.get('error_displayed') 362 error_value = item.get('error_value') 363 minimum_displayed = item.get('minimum_displayed') 364 minimum_value = item.get('minimum_value') 365 maximum_displayed = item.get('maximum_displayed') 366 maximum_value = item.get('maximum_value') 367 unit = item.get('unit') 368 list.append([selected_to_fit, name, value, "+/-",[error_displayed, error_value], 369 [minimum_displayed,minimum_value],[maximum_displayed,maximum_value], unit]) 370 371 def fromXML(self, file=None, node=None): 372 """ 373 Load fitting state from a file 374 375 @param file: .fitv file 376 @param node: node of a XML document to read from 377 """ 378 379 if file is not None: 380 raise RuntimeError, "PageState no longer supports non-CanSAS format for fitting files" 381 382 if node.get('version')\ 383 and node.get('version') == '1.0': 384 385 # Get file name 386 entry = get_content('ns:filename', node) 387 if entry is not None: 388 self.file = entry.text.strip() 389 390 # Parse fitting attributes 391 entry = get_content('ns:Attributes', node) 392 if entry is not None: 393 for item in list_of_state_attributes: 394 field = get_content('ns:%s'%item[0], entry) 395 if field is not None: 396 if item[2] == "string": 397 exec "self.%s= str(field.text)"%item[1] 398 elif item[2] == "bool": 399 try: 400 exec "self.%s= field.get(str(%s))"%(item[1], item[0]) 401 except: 402 exec "self.%s = None"%item[1] 403 else: 404 try: 405 exec "self.%s = float(field.get(%s))"%(item[1], item[0]) 406 except: 407 exec "self.%s = None"%item[1] 408 409 for item in list_of_state_parameters: 410 field = get_content("ns:%s"%item[0], entry) 411 self._fromXML_helper(node=field, list=self.parameters) 412 413 414 class Reader(CansasReader): 415 """ 416 Class to load a .fitv fitting file 417 """ 418 ## File type 419 type_name = "Fitting" 420 421 ## Wildcards 422 type = ["Fitting files (*.fitv)|*.fitv"] 423 ## List of allowed extensions 424 ext=['.fitv', '.FITV'] 425 426 def __init__(self, call_back=None, cansas=True): 427 """ 428 Initialize the call-back method to be called 429 after we load a file 430 @param call_back: call-back method 431 @param cansas: True = files will be written/read in CanSAS format 432 False = write CanSAS format 433 434 """ 435 ## Call back method to be executed after a file is read 436 self.call_back = call_back 437 ## CanSAS format flag 438 self.cansas = cansas 439 440 def read(self, path): 441 """ 442 Load a new P(r) inversion state from file 443 444 @param path: file path 445 @return: None 446 """ 447 if self.cansas==True: 448 return self._read_cansas(path) 449 else: 450 return self._read_standalone(path) 451 452 def _data2d_to_xml_doc(self): 453 """ 454 Create an XML document to contain the content of a Data2D 455 456 @param datainfo: Data2D object 457 """ 458 if not issubclass(datainfo.__class__, Data2D): 459 raise RuntimeError, "The cansas writer expects a Data2D instance" 460 461 doc = xml.dom.minidom.Document() 462 main_node = doc.createElement("SASroot") 463 main_node.setAttribute("version", self.version) 464 465 doc.appendChild(main_node) 466 467 entry_node = doc.createElement("SASentry") 468 main_node.appendChild(entry_node) 469 470 write_node(doc, entry_node, "Title", datainfo.title) 471 472 for item in datainfo.run: 473 runname = {} 474 if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1: 475 runname = {'name': datainfo.run_name[item] } 476 write_node(doc, entry_node, "Run", item, runname) 477 478 # Data info 479 node = doc.createElement("SASdata") 480 entry_node.appendChild(node) 481 482 for i in range(len(datainfo.x)): 483 pt = doc.createElement("Idata") 484 node.appendChild(pt) 485 write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit}) 486 if len(datainfo.y)>=i: 487 write_node(doc, pt, "I", datainfo.y[i], {'unit':datainfo.y_unit}) 488 if datainfo.dx !=None and len(datainfo.dx)>=i: 489 write_node(doc, pt, "Qdev", datainfo.dx[i], {'unit':datainfo.x_unit}) 490 if datainfo.dy !=None and len(datainfo.dy)>=i: 491 write_node(doc, pt, "Idev", datainfo.dy[i], {'unit':datainfo.y_unit}) 492 493 494 # Sample info 495 sample = doc.createElement("SASsample") 496 if datainfo.sample.name is not None: 497 sample.setAttribute("name", str(datainfo.sample.name)) 498 entry_node.appendChild(sample) 499 write_node(doc, sample, "ID", str(datainfo.sample.ID)) 500 write_node(doc, sample, "thickness", datainfo.sample.thickness, {"unit":datainfo.sample.thickness_unit}) 501 write_node(doc, sample, "transmission", datainfo.sample.transmission) 502 write_node(doc, sample, "temperature", datainfo.sample.temperature, {"unit":datainfo.sample.temperature_unit}) 503 504 for item in datainfo.sample.details: 505 write_node(doc, sample, "details", item) 506 507 pos = doc.createElement("position") 508 written = write_node(doc, pos, "x", datainfo.sample.position.x, {"unit":datainfo.sample.position_unit}) 509 written = written | write_node(doc, pos, "y", datainfo.sample.position.y, {"unit":datainfo.sample.position_unit}) 510 written = written | write_node(doc, pos, "z", datainfo.sample.position.z, {"unit":datainfo.sample.position_unit}) 511 if written == True: 512 sample.appendChild(pos) 513 514 ori = doc.createElement("orientation") 515 written = write_node(doc, ori, "roll", datainfo.sample.orientation.x, {"unit":datainfo.sample.orientation_unit}) 516 written = written | write_node(doc, ori, "pitch", datainfo.sample.orientation.y, {"unit":datainfo.sample.orientation_unit}) 517 written = written | write_node(doc, ori, "yaw", datainfo.sample.orientation.z, {"unit":datainfo.sample.orientation_unit}) 518 if written == True: 519 sample.appendChild(ori) 520 521 # Instrument info 522 instr = doc.createElement("SASinstrument") 523 entry_node.appendChild(instr) 524 525 write_node(doc, instr, "name", datainfo.instrument) 526 527 # Source 528 source = doc.createElement("SASsource") 529 if datainfo.source.name is not None: 530 source.setAttribute("name", str(datainfo.source.name)) 531 instr.appendChild(source) 532 533 write_node(doc, source, "radiation", datainfo.source.radiation) 534 write_node(doc, source, "beam_shape", datainfo.source.beam_shape) 535 size = doc.createElement("beam_size") 536 if datainfo.source.beam_size_name is not None: 537 size.setAttribute("name", str(datainfo.source.beam_size_name)) 538 written = write_node(doc, size, "x", datainfo.source.beam_size.x, {"unit":datainfo.source.beam_size_unit}) 539 written = written | write_node(doc, size, "y", datainfo.source.beam_size.y, {"unit":datainfo.source.beam_size_unit}) 540 written = written | write_node(doc, size, "z", datainfo.source.beam_size.z, {"unit":datainfo.source.beam_size_unit}) 541 if written == True: 542 source.appendChild(size) 543 544 write_node(doc, source, "wavelength", datainfo.source.wavelength, {"unit":datainfo.source.wavelength_unit}) 545 write_node(doc, source, "wavelength_min", datainfo.source.wavelength_min, {"unit":datainfo.source.wavelength_min_unit}) 546 write_node(doc, source, "wavelength_max", datainfo.source.wavelength_max, {"unit":datainfo.source.wavelength_max_unit}) 547 write_node(doc, source, "wavelength_spread", datainfo.source.wavelength_spread, {"unit":datainfo.source.wavelength_spread_unit}) 548 549 # Collimation 550 for item in datainfo.collimation: 551 coll = doc.createElement("SAScollimation") 552 if item.name is not None: 553 coll.setAttribute("name", str(item.name)) 554 instr.appendChild(coll) 555 556 write_node(doc, coll, "length", item.length, {"unit":item.length_unit}) 557 558 for apert in item.aperture: 559 ap = doc.createElement("aperture") 560 if apert.name is not None: 561 ap.setAttribute("name", str(apert.name)) 562 if apert.type is not None: 563 ap.setAttribute("type", str(apert.type)) 564 coll.appendChild(ap) 565 566 write_node(doc, ap, "distance", apert.distance, {"unit":apert.distance_unit}) 567 568 size = doc.createElement("size") 569 if apert.size_name is not None: 570 size.setAttribute("name", str(apert.size_name)) 571 written = write_node(doc, size, "x", apert.size.x, {"unit":apert.size_unit}) 572 written = written | write_node(doc, size, "y", apert.size.y, {"unit":apert.size_unit}) 573 written = written | write_node(doc, size, "z", apert.size.z, {"unit":apert.size_unit}) 574 if written == True: 575 ap.appendChild(size) 576 577 # Detectors 578 for item in datainfo.detector: 579 det = doc.createElement("SASdetector") 580 written = write_node(doc, det, "name", item.name) 581 written = written | write_node(doc, det, "SDD", item.distance, {"unit":item.distance_unit}) 582 written = written | write_node(doc, det, "slit_length", item.slit_length, {"unit":item.slit_length_unit}) 583 if written == True: 584 instr.appendChild(det) 585 586 off = doc.createElement("offset") 587 written = write_node(doc, off, "x", item.offset.x, {"unit":item.offset_unit}) 588 written = written | write_node(doc, off, "y", item.offset.y, {"unit":item.offset_unit}) 589 written = written | write_node(doc, off, "z", item.offset.z, {"unit":item.offset_unit}) 590 if written == True: 591 det.appendChild(off) 592 593 center = doc.createElement("beam_center") 594 written = write_node(doc, center, "x", item.beam_center.x, {"unit":item.beam_center_unit}) 595 written = written | write_node(doc, center, "y", item.beam_center.y, {"unit":item.beam_center_unit}) 596 written = written | write_node(doc, center, "z", item.beam_center.z, {"unit":item.beam_center_unit}) 597 if written == True: 598 det.appendChild(center) 599 600 pix = doc.createElement("pixel_size") 601 written = write_node(doc, pix, "x", item.pixel_size.x, {"unit":item.pixel_size_unit}) 602 written = written | write_node(doc, pix, "y", item.pixel_size.y, {"unit":item.pixel_size_unit}) 603 written = written | write_node(doc, pix, "z", item.pixel_size.z, {"unit":item.pixel_size_unit}) 604 if written == True: 605 det.appendChild(pix) 606 607 ori = doc.createElement("orientation") 608 written = write_node(doc, ori, "roll", item.orientation.x, {"unit":item.orientation_unit}) 609 written = written | write_node(doc, ori, "pitch", item.orientation.y, {"unit":item.orientation_unit}) 610 written = written | write_node(doc, ori, "yaw", item.orientation.z, {"unit":item.orientation_unit}) 611 if written == True: 612 det.appendChild(ori) 613 614 615 # Processes info 616 for item in datainfo.process: 617 node = doc.createElement("SASprocess") 618 entry_node.appendChild(node) 619 620 write_node(doc, node, "name", item.name) 621 write_node(doc, node, "date", item.date) 622 write_node(doc, node, "description", item.description) 623 for term in item.term: 624 value = term['value'] 625 del term['value'] 626 write_node(doc, node, "term", value, term) 627 for note in item.notes: 628 write_node(doc, node, "SASprocessnote", note) 629 630 # Return the document, and the SASentry node associated with 631 # the data we just wrote 632 return doc, entry_node 633 634 def _read_standalone(self, path): 635 """ 636 Load a new P(r) inversion state from file. 637 The P(r) node is assumed to be the top element. 638 639 @param path: file path 640 @return: None 641 """ 642 # Read the new state from file 643 state = PageState() 644 state.fromXML(file=path) 645 # Call back to post the new state 646 self.call_back(state) 647 return None 648 649 def _parse_state(self, entry): 650 """ 651 Read a fit result from an XML node 652 @param entry: XML node to read from 653 @return: PageState object 654 """ 655 # Create an empty state 656 state = PageState() 657 # Locate the P(r) node 658 try: 659 nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, namespaces={'ns': CANSAS_NS}) 660 state.fromXML(node=nodes[0]) 661 except: 662 logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value) 663 664 return state 665 666 def _read_cansas(self, path): 667 """ 668 Load data and P(r) information from a CanSAS XML file. 669 670 @param path: file path 671 @return: Data1D object if a single SASentry was found, 672 or a list of Data1D objects if multiple entries were found, 673 or None of nothing was found 674 @raise RuntimeError: when the file can't be opened 675 @raise ValueError: when the length of the data vectors are inconsistent 676 """ 677 output = [] 678 try: 679 if os.path.isfile(path): 680 basename = os.path.basename(path) 681 root, extension = os.path.splitext(basename) 682 #TODO: eventually remove the check for .xml once 683 # the P(r) writer/reader is truly complete. 684 if extension.lower() in self.ext or \ 685 extension.lower() == '.xml': 686 687 tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 688 # Check the format version number 689 # Specifying the namespace will take care of the file format version 690 root = tree.getroot() 691 entry_list = root.xpath('/ns:SASroot/ns:SASentry', namespaces={'ns': CANSAS_NS}) 692 for entry in entry_list: 693 sas_entry = self._parse_entry(entry) 694 fitstate = self._parse_state(entry) 695 sas_entry.meta_data['fitstate'] = fitstate 696 sas_entry.filename = fitstate.file 697 output.append(sas_entry) 698 699 else: 700 raise RuntimeError, "%s is not a file" % path 701 702 # Return output consistent with the loader's api 703 if len(output)==0: 704 return None 705 elif len(output)==1: 706 # Call back to post the new state 707 state = output[0].meta_data['fitstate'] 708 if state is not None and state.is_data is not None: 709 exec 'output[0].is_data = state.is_data' 710 711 output[0].filename = state.data_name 712 state.data = output[0] 713 state.data.name = state.data_name 714 state.data.id = state.data_id 715 state.data.group_id = state.data_group_id 716 self.call_back(state=state, datainfo=output[0]) 717 return output[0] 718 else: 719 return output 720 except: 721 raise 722 723 def write(self, filename, datainfo=None, fitstate=None): 724 """ 725 Write the content of a Data1D as a CanSAS XML file 726 727 @param filename: name of the file to write 728 @param datainfo: Data1D object 729 @param fitstate: PageState object 730 """ 731 # Sanity check 732 if self.cansas == True: 733 734 # Add fitting information to the XML document 735 if fitstate is not None: 736 if fitstate.data is None: 737 data = DataLoader.data_info.Data1D(x=[], y=[]) 738 elif issubclass(fitstate.data.__class__, DataLoader.data_info.Data1D): 739 data = fitstate.data 740 doc, sasentry = self._to_xml_doc(data) 741 else: 742 data = fitstate.data 743 doc, sasentry = self._data2d_to_xml_doc(data) 744 fitstate.toXML(doc=doc, entry_node=sasentry) 745 # Write the XML document 746 fd = open(filename, 'w') 747 fd.write(doc.toprettyxml()) 748 fd.close() 749 else: 750 fitstate.toXML(file=filename) 751 752 753 if __name__ == "__main__": 754 state = PageState(parent=None) 755 state.toXML() 756
Note: See TracChangeset
for help on using the changeset viewer.