Changeset 8b21fa7 in sasview for src/sas/perspectives/pr/inversion_state.py
- Timestamp:
- Mar 6, 2015 2:05:50 PM (9 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:
- b1e609c
- Parents:
- c1c14ba
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/perspectives/pr/inversion_state.py
rc4f6851 r8b21fa7 5 5 #This software was developed by the University of Tennessee as part of the 6 6 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 7 #project funded by the US National Science Foundation. 7 #project funded by the US National Science Foundation. 8 8 # 9 9 #See the license text in license.txt … … 26 26 27 27 # Translation of names between stored and object data 28 ## List of P(r) inversion inputs 29 in_list = [["nterms","nfunc"],30 ["d_max", 31 ["alpha", 32 ["slit_width", 33 ["slit_height", 34 ["qmin", 35 ["qmax", 36 ["estimate_bck", "estimate_bck"]] 28 ## List of P(r) inversion inputs 29 in_list = [["nterms", "nfunc"], 30 ["d_max", "d_max"], 31 ["alpha", "alpha"], 32 ["slit_width", "width"], 33 ["slit_height", "height"], 34 ["qmin", "qmin"], 35 ["qmax", "qmax"], 36 ["estimate_bck", "estimate_bck"]] 37 37 38 38 ## List of P(r) inversion outputs 39 39 out_list = [["elapsed", "elapsed"], 40 ["rg","rg"],41 ["iq0","iq0"],42 ["bck","bck"],43 ["chi2","chi2"],44 ["osc","osc"],45 ["pos","pos"],46 ["pos_err", "pos_err"],47 ["alpha_estimate", "alpha_estimate"],48 ["nterms_estimate", "nterms_estimate"]]40 ["rg", "rg"], 41 ["iq0", "iq0"], 42 ["bck", "bck"], 43 ["chi2", "chi2"], 44 ["osc", "osc"], 45 ["pos", "pos"], 46 ["pos_err", "pos_err"], 47 ["alpha_estimate", "alpha_estimate"], 48 ["nterms_estimate", "nterms_estimate"]] 49 49 50 50 class InversionState(object): … … 56 56 Default values 57 57 """ 58 # Input 59 self.file 58 # Input 59 self.file = None 60 60 self.estimate_bck = False 61 61 self.timestamp = time.time() 62 62 63 63 # Inversion parameters 64 64 self.nfunc = None 65 65 self.d_max = None 66 66 self.alpha = None 67 67 68 68 # Slit parameters 69 69 self.height = None 70 self.width 71 70 self.width = None 71 72 72 # Q range 73 self.qmin 74 self.qmax 75 73 self.qmin = None 74 self.qmax = None 75 76 76 # Outputs 77 77 self.elapsed = None 78 self.rg 79 self.iq0 80 self.bck 81 self.chi2 82 self.osc 83 self.pos 78 self.rg = None 79 self.iq0 = None 80 self.bck = None 81 self.chi2 = None 82 self.osc = None 83 self.pos = None 84 84 self.pos_err = None 85 85 86 86 # Estimates 87 87 self.alpha_estimate = None 88 88 self.nterms_estimate = None 89 89 90 90 # Data 91 self.q 92 self.iq_obs 91 self.q = None 92 self.iq_obs = None 93 93 self.iq_calc = None 94 94 95 95 # Coefficients 96 96 self.coefficients = None 97 97 self.covariance = None 98 98 99 99 def __str__(self): 100 100 """ 101 101 Pretty print 102 102 103 103 :return: string representing the state 104 105 """ 106 state 104 105 """ 106 state = "File: %s\n" % self.file 107 107 state += "Timestamp: %s\n" % self.timestamp 108 108 state += "Estimate bck: %s\n" % str(self.estimate_bck) … … 110 110 state += "D_max: %s\n" % str(self.d_max) 111 111 state += "Alpha: %s\n" % str(self.alpha) 112 112 113 113 state += "Slit height: %s\n" % str(self.height) 114 114 state += "Slit width: %s\n" % str(self.width) 115 115 116 116 state += "Qmin: %s\n" % str(self.qmin) 117 117 state += "Qmax: %s\n" % str(self.qmax) 118 118 119 119 state += "\nEstimates:\n" 120 120 state += " Alpha: %s\n" % str(self.alpha_estimate) 121 121 state += " Nterms: %s\n" % str(self.nterms_estimate) 122 122 123 123 state += "\nOutputs:\n" 124 124 state += " Elapsed: %s\n" % str(self.elapsed) … … 130 130 state += " Positive: %s\n" % str(self.pos) 131 131 state += " 1-sigma pos:%s\n" % str(self.pos_err) 132 132 133 133 return state 134 134 135 135 def toXML(self, file="pr_state.prv", doc=None, entry_node=None): 136 136 """ 137 137 Writes the state of the InversionControl panel to file, as XML. 138 138 139 139 Compatible with standalone writing, or appending to an 140 140 already existing XML document. In that case, the XML document 141 is required. An optional entry node in the XML document 141 is required. An optional entry node in the XML document 142 142 may also be given. 143 143 144 144 :param file: file to write to 145 145 :param doc: XML document object [optional] 146 :param entry_node: XML node within the XML document at which 146 :param entry_node: XML node within the XML document at which 147 147 we will append the data [optional] 148 148 149 149 """ 150 150 #TODO: Get this to work … … 154 154 if doc is None: 155 155 impl = getDOMImplementation() 156 157 doc_type = impl.createDocumentType(PRNODE_NAME, "1.0", "1.0") 158 156 157 doc_type = impl.createDocumentType(PRNODE_NAME, "1.0", "1.0") 158 159 159 newdoc = impl.createDocument(None, PRNODE_NAME, doc_type) 160 160 top_element = newdoc.documentElement … … 167 167 else: 168 168 entry_node.appendChild(top_element) 169 169 170 170 attr = newdoc.createAttribute("version") 171 171 attr.nodeValue = '1.0' 172 172 top_element.setAttributeNode(attr) 173 173 174 174 # File name 175 175 element = newdoc.createElement("filename") … … 179 179 element.appendChild(newdoc.createTextNode(str(file))) 180 180 top_element.appendChild(element) 181 181 182 182 element = newdoc.createElement("timestamp") 183 183 element.appendChild(newdoc.createTextNode(time.ctime(self.timestamp))) … … 186 186 element.setAttributeNode(attr) 187 187 top_element.appendChild(element) 188 188 189 189 # Inputs 190 190 inputs = newdoc.createElement("inputs") 191 191 top_element.appendChild(inputs) 192 192 193 193 for item in in_list: 194 194 element = newdoc.createElement(item[0]) 195 195 element.appendChild(newdoc.createTextNode(str(getattr(self, item[1])))) 196 196 inputs.appendChild(element) 197 197 198 198 # Outputs 199 199 outputs = newdoc.createElement("outputs") 200 200 top_element.appendChild(outputs) 201 201 202 202 for item in out_list: 203 203 element = newdoc.createElement(item[0]) 204 204 element.appendChild(newdoc.createTextNode(str(getattr(self, item[1])))) 205 205 outputs.appendChild(element) 206 206 207 207 # Save output coefficients and its covariance matrix 208 208 element = newdoc.createElement("coefficients") … … 212 212 element.appendChild(newdoc.createTextNode(str(self.covariance))) 213 213 outputs.appendChild(element) 214 214 215 215 # Save the file 216 216 if doc is None: … … 225 225 """ 226 226 Load a P(r) inversion state from a file 227 227 228 228 :param file: .prv file 229 229 :param node: node of a XML document to read from 230 230 231 231 """ 232 232 if file is not None: … … 234 234 msg += " format for P(r) files" 235 235 raise RuntimeError, msg 236 236 237 237 if node.get('version') and node.get('version') == '1.0': 238 238 239 239 # Get file name 240 240 entry = get_content('ns:filename', node) 241 241 if entry is not None: 242 242 self.file = entry.text.strip() 243 243 244 244 # Get time stamp 245 245 entry = get_content('ns:timestamp', node) … … 251 251 msg += "timestamp\n %s" % sys.exc_value 252 252 logging.error(msg) 253 253 254 254 # Parse inversion inputs 255 255 entry = get_content('ns:inputs', node) … … 265 265 if input_field is not None: 266 266 try: 267 self.estimate_bck = input_field.text.strip() =='True'267 self.estimate_bck = input_field.text.strip() == 'True' 268 268 except: 269 269 self.estimate_bck = False 270 270 271 271 # Parse inversion outputs 272 272 entry = get_content('ns:outputs', node) … … 280 280 except: 281 281 setattr(self, item[1], None) 282 282 283 283 # Look for coefficients 284 284 # Format is [value, value, value, value] … … 286 286 if coeff is not None: 287 287 # Remove brackets 288 c_values = coeff.text.strip().replace('[', '')289 c_values = c_values.replace(']', '')288 c_values = coeff.text.strip().replace('[', '') 289 c_values = c_values.replace(']', '') 290 290 toks = c_values.split() 291 291 self.coefficients = [] … … 308 308 logging.error(err_msg) 309 309 self.coefficients = None 310 310 311 311 # Look for covariance matrix 312 312 # Format is [ [value, value], [value, value] ] … … 320 320 if len(row) == 0: continue 321 321 # Remove end bracket 322 row = row.replace(']', '')322 row = row.replace(']', '') 323 323 c_values = row.split() 324 324 cov_row = [] … … 345 345 logging.error(err_msg) 346 346 self.covariance = None 347 347 348 348 class Reader(CansasReader): 349 349 """ … … 352 352 ## File type 353 353 type_name = "P(r)" 354 354 355 355 ## Wildcards 356 356 type = ["P(r) files (*.prv)|*.prv", 357 357 "SASView files (*.svs)|*.svs"] 358 358 ## List of allowed extensions 359 ext = ['.prv', '.PRV', '.svs', '.SVS'] 360 359 ext = ['.prv', '.PRV', '.svs', '.SVS'] 360 361 361 def __init__(self, call_back, cansas=True): 362 362 """ 363 363 Initialize the call-back method to be called 364 364 after we load a file 365 365 366 366 :param call_back: call-back method 367 367 :param cansas: True = files will be written/read in CanSAS format 368 368 False = write CanSAS format 369 369 370 370 """ 371 371 ## Call back method to be executed after a file is read … … 374 374 self.cansas = cansas 375 375 self.state = None 376 376 377 377 def read(self, path): 378 """ 378 """ 379 379 Load a new P(r) inversion state from file 380 380 381 381 :param path: file path 382 382 383 383 :return: None 384 385 """ 386 if self.cansas ==True:384 385 """ 386 if self.cansas == True: 387 387 return self._read_cansas(path) 388 388 else: 389 389 return self._read_standalone(path) 390 390 391 391 def _read_standalone(self, path): 392 """ 392 """ 393 393 Load a new P(r) inversion state from file. 394 394 The P(r) node is assumed to be the top element. 395 395 396 396 :param path: file path 397 397 398 398 :return: None 399 399 400 400 """ 401 401 # Read the new state from file 402 402 state = InversionState() 403 403 state.fromXML(file=path) 404 404 405 405 # Call back to post the new state 406 406 self.state = state 407 407 #self.call_back(state) 408 408 return None 409 409 410 410 def _parse_prstate(self, entry): 411 411 """ 412 412 Read a p(r) inversion result from an XML node 413 414 :param entry: XML node to read from 415 413 414 :param entry: XML node to read from 415 416 416 :return: InversionState object 417 417 418 418 """ 419 419 state = None 420 420 421 421 # Locate the P(r) node 422 422 try: 423 423 nodes = entry.xpath('ns:%s' % PRNODE_NAME, 424 424 namespaces={'ns': CANSAS_NS}) 425 if nodes != []:425 if nodes != []: 426 426 # Create an empty state 427 state = 427 state = InversionState() 428 428 state.fromXML(node=nodes[0]) 429 429 except: … … 431 431 msg += "information.\n %s" % sys.exc_value 432 432 logging.info(msg) 433 433 434 434 return state 435 435 436 436 def _read_cansas(self, path): 437 """ 437 """ 438 438 Load data and P(r) information from a CanSAS XML file. 439 439 440 440 :param path: file path 441 442 :return: Data1D object if a single SASentry was found, 441 442 :return: Data1D object if a single SASentry was found, 443 443 or a list of Data1D objects if multiple entries were found, 444 444 or None of nothing was found 445 445 446 446 :raise RuntimeError: when the file can't be opened 447 447 :raise ValueError: when the length of the data vectors are inconsistent 448 448 449 449 """ 450 450 output = [] 451 451 452 452 if os.path.isfile(path): 453 basename 453 basename = os.path.basename(path) 454 454 root, extension = os.path.splitext(basename) 455 455 #TODO: eventually remove the check for .xml once 456 456 # the P(r) writer/reader is truly complete. 457 457 if extension.lower() in self.ext or extension.lower() == '.xml': 458 458 459 459 tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 460 460 # Check the format version number … … 462 462 #format version 463 463 root = tree.getroot() 464 464 465 465 entry_list = root.xpath('/ns:SASroot/ns:SASentry', 466 466 namespaces={'ns': CANSAS_NS}) … … 477 477 else: 478 478 raise RuntimeError, "%s is not a file" % path 479 479 480 480 # Return output consistent with the loader's api 481 481 if len(output) == 0: … … 483 483 elif len(output) == 1: 484 484 # Call back to post the new state 485 self.call_back(output[0].meta_data['prstate'], datainfo =output[0])485 self.call_back(output[0].meta_data['prstate'], datainfo=output[0]) 486 486 #self.state = output[0].meta_data['prstate'] 487 487 return output[0] 488 488 else: 489 return output 490 491 489 return output 490 491 492 492 def write(self, filename, datainfo=None, prstate=None): 493 493 """ 494 494 Write the content of a Data1D as a CanSAS XML file 495 495 496 496 :param filename: name of the file to write 497 497 :param datainfo: Data1D object 498 498 :param prstate: InversionState object 499 499 500 500 """ 501 501 # Sanity check 502 502 if self.cansas == True: 503 doc = self.write_toXML(datainfo, prstate) 503 doc = self.write_toXML(datainfo, prstate) 504 504 # Write the XML document 505 505 fd = open(filename, 'w') … … 508 508 else: 509 509 prstate.toXML(file=filename) 510 510 511 511 def write_toXML(self, datainfo=None, state=None): 512 512 """ 513 513 Write toXML, a helper for write() 514 514 515 515 : return: xml doc 516 516 """ 517 517 if datainfo is None: 518 datainfo = Data1D(x=[], y=[]) 518 datainfo = Data1D(x=[], y=[]) 519 519 elif not issubclass(datainfo.__class__, Data1D): 520 520 msg = "The cansas writer expects a Data1D " 521 521 msg += "instance: %s" % str(datainfo.__class__.__name__) 522 522 raise RuntimeError, msg 523 523 524 524 # Create basic XML document 525 525 doc, sasentry = self._to_xml_doc(datainfo) 526 526 527 527 # Add the invariant information to the XML document 528 528 if state is not None: 529 529 doc = state.toXML(doc=doc, entry_node=sasentry) 530 531 return doc 532 530 531 return doc
Note: See TracChangeset
for help on using the changeset viewer.