def addVector(self,target,name,valueDict,root=None,pivotVal=None): """ Adds a node entry named "name" with value "value" to "target" node, such as <root> <target> <name> <with_respect_to_name1>value1 <with_respect_to_name2>value2 <with_respect_to_name3>value3 The valueDict should be as {with_respect_to_name1:value1, with_respect_to_name2:value2} For example, if the "name" is sensitivity_coefficients, each entry would be the sensitivity of "target" to "with_respect_to" parameters. @ In, target, string, target parameter to add node value to @ In, name, string, name of characteristic of target to add @ In, valueDict, dict, name:value @ In, root, xml.etree.ElementTree.Element, optional, root to add to @ In, pivotVal, float, optional, unused (for consistency with dynamic mode) @ Out, None """ if root is None: root = self.tree.getroot() targ = self._findTarg(root,target) nameNode = xmlUtils.newNode(name) for key,value in valueDict.items(): nameNode.append(xmlUtils.newNode(key,text=value)) targ.append(nameNode)
def writeXML(self, writeTo, params): """ Allows the engine to put whatever it wants into an XML to print to file. @ In, writeTo, xmlUtils.StaticXmlElement, entity to write to @ In, params, dict, trained parameters as from self.characterize @ Out, None """ for target, info in params.items(): base = xmlUtils.newNode(target) writeTo.append(base) base.append( xmlUtils.newNode('fit_intercept', text=f'{float(info["intercept"]):1.9e}')) for period in info['coeffs']: periodNode = xmlUtils.newNode('waveform', attrib={ 'period': f'{period:1.9e}', 'frequency': f'{(1.0/period):1.9e}' }) base.append(periodNode) for stat, value in sorted(list(info['coeffs'][period].items()), key=lambda x: x[0]): periodNode.append( xmlUtils.newNode(stat, text=f'{value:1.9e}'))
def createRegressionXML(targets, degree): """ Return regression XML node for RAVEN input. @ In, targets, list[str], list of strings describing targets for current RAVEN run. @ In, degree, int, the degree of polynomial to fit. @ Out, xml, xml.etree.ElementTree.Element, new node """ xml = xmlUtils.newNode('Regression', attrib={'target': ','.join(targets)}) xml.append(xmlUtils.newNode('degree', text=f'{degree}')) return xml
def createWaveletXML(targets, family): """ Return Wavelet XML node for RAVEN input. @ In, targets, list[str], list of strings describing targets for current RAVEN run. @ In, family, str, the family of wavelet to use. @ Out, xml, xml.etree.ElementTree.Element, new node """ xml = xmlUtils.newNode('Wavelet', attrib={'target': ','.join(targets)}) xml.append(xmlUtils.newNode('family', text=family)) return xml
def writeXML(self, writeTo, params): """ Allows the engine to put whatever it wants into an XML to print to file. @ In, writeTo, xmlUtils.StaticXmlElement, entity to write to @ In, params, dict, trained parameters as from self.characterize @ Out, None """ for target, info in params.items(): base = xmlUtils.newNode(target) writeTo.append(base) for name, value in info['results'].items(): base.append(xmlUtils.newNode(name, text=','.join([str(v) for v in value])))
def _samplerVariable(self, xml, varName): """ Adds a variable block to a Sampler @ In, xml, xml.etree.ElementTree.Element, specific Sampler node to add to @ In, varName, str, name of variable @ Out, None """ var = xmlUtils.newNode('variable', attrib={'name': varName}) var.append( xmlUtils.newNode( 'distribution', text=self.namingTemplates['distribution'].format(var=varName))) xml.append(var)
def writeXML(self, writeTo, params): """ Allows the engine to put whatever it wants into an XML to print to file. @ In, writeTo, xmlUtils.StaticXmlElement, entity to write to @ In, params, dict, trained parameters as from self.characterize @ Out, None """ for target, info in params.items(): base = xmlUtils.newNode(target) writeTo.append(base) for name, value in info['model'].items(): if name == 'object': continue base.append(xmlUtils.newNode(name, text=f'{float(value):1.9e}'))
def _applyMetrics(self, template, uncertain, metrics): """ sets up metrics for statistical postprocessing @ In, template, xml.etree.ElementTree.Element, root of template XML @ In, uncertain, list, list of variables that are uncertain @ In, metrics, list, list of metrics to use (or None if none given) @ Out, template, xml.etree.ElementTree.Element, modified root of template XML """ if metrics is None: metrics = ['mean'] uncVars = ','.join(uncertain) ## add to PostProcessor, also output DataObject # find the postprocessor statsPP = template.find('Models').find('PostProcessor') # find the stats data object dataObjs = template.find('DataObjects').findall('PointSet') for dataObj in dataObjs: if dataObj.attrib['name'] == 'stats': break outputsNode = dataObj.find('Output') for metric in metrics: if metric == 'mean': statsPP.append( xmlUtils.newNode('expectedValue', attrib={'prefix': 'mean'}, text=uncVars)) for var in uncertain: self._updateCommaSeperatedList(outputsNode, '{}_{}'.format(metric, var)) elif metric == 'std': statsPP.append( xmlUtils.newNode('sigma', attrib={'prefix': 'std'}, text=uncVars)) for var in uncertain: self._updateCommaSeperatedList(outputsNode, '{}_{}'.format(metric, var)) elif metric == 'percentile': statsPP.append( xmlUtils.newNode('percentile', attrib={'prefix': 'pct'}, text=uncVars)) for var in uncertain: self._updateCommaSeperatedList( outputsNode, '{}_{}'.format('pct_5', var)) self._updateCommaSeperatedList( outputsNode, '{}_{}'.format('pct_95', var)) return template
def writeXML(self, writeTo, targets=None, skip=None): """ Write out ARMA information @ In, writeTo, xmlUtils.StaticXmlElement, entity to write to @ In, targets, list, optional, unused @ In, skip, list, optional, unused @ Out, None """ # do everything that Segments do Segments.writeXML(self, writeTo, targets, skip) # add some stuff specific to clustering main = writeTo.getRoot() labels = self._clusterInfo['labels'] for i, repRom in enumerate(self._roms): # find associated node modify = xmlUtils.findPath(main, 'SegmentROM[@segment={}]'.format(i)) # make changes to reflect being a cluster modify.tag = 'ClusterROM' modify.attrib['cluster'] = modify.attrib.pop('segment') modify.append( xmlUtils.newNode( 'segments_represented', text=', '.join( str(x) for x in np.arange(len(labels))[labels == i])))
def writeXML(self, writeTo, params): """ Allows the engine to put whatever it wants into an XML to print to file. @ In, writeTo, xmlUtils.StaticXmlElement, entity to write to @ In, params, dict, trained parameters as from self.characterize @ Out, None """ for target, info in params.items(): base = xmlUtils.newNode(target) writeTo.append(base) base.append(xmlUtils.newNode('constant', text=f'{float(info["arma"]["const"]):1.9e}')) for p, ar in enumerate(info['arma']['ar']): base.append(xmlUtils.newNode(f'AR_{p}', text=f'{float(ar):1.9e}')) for q, ma in enumerate(info['arma']['ma']): base.append(xmlUtils.newNode(f'MA_{q}', text=f'{float(ma):1.9e}')) base.append(xmlUtils.newNode('variance', text=f'{float(info["arma"]["var"]):1.9e}'))
def addScalar(self, target, name, value, root=None, pivotVal=None, attrs=None): """ Adds a node entry named "name" with value "value" to "target" node, such as <root> <target> <name>value<name> @ In, target, string, target parameter to add node value to @ In, name, string, name of characteristic of target to add @ In, value, string/float/etc, value of characteristic @ In, root, xml.etree.ElementTree.Element, optional, root to add to @ In, pivotVal, float, optional, unused (for consistency with dynamic mode) @ In, attrs, dict, optional, dictionary of attributes to be stored in the node @ Out, None """ if root is None: root = self.tree.getroot() else: if utils.isString(root): root = self._findTarg(self.tree.getroot(), root) #note: illegal unicode characters are checked for in xmlUtils methods targ = self._findTarg(root, target) if root.tag != target.strip() else root targ.append(xmlUtils.newNode(name, text=value, attrib=attrs))
def addVector(self, target, name, valueDict, root=None, pivotVal=None, attrs=None, valueAttrsDict=None): """ Adds a node entry named "name" with value "value" to "target" node, such as <root> <target> <name> <with_respect_to_name1>value1 <with_respect_to_name2>value2 <with_respect_to_name3>value3 The valueDict should be as {with_respect_to_name1:value1, with_respect_to_name2:value2} For example, if the "name" is sensitivity_coefficients, each entry would be the sensitivity of "target" to "with_respect_to" parameters. @ In, target, string, target parameter to add node value to @ In, name, string, name of characteristic of target to add @ In, valueDict, dict, name:value @ In, root, xml.etree.ElementTree.Element, optional, root to add to @ In, pivotVal, float, optional, unused (for consistency with dynamic mode) @ In, attrs, dict, optional, dictionary of attributes to be stored in the node (name) @ In, valueAttrsDict, dict, optional, dictionary of attributes to be stored along the subnodes identified by the valueDict dictionary @ Out, None """ valAttribsDict = {} if valueAttrsDict is not None: valAttribsDict = valueAttrsDict if root is None: root = self.tree.getroot() else: if utils.isString(root): root = self._findTarg(self.tree.getroot(), root) targ = self._findTarg(root, target) if root.tag != target.strip() else root nameNode = xmlUtils.newNode(name, attrib=attrs) for key, value in valueDict.items(): nameNode.append( xmlUtils.newNode(key, text=value, attrib=valAttribsDict.get(key, None))) targ.append(nameNode)
def _normalDistribution(self, xml, varName, mean, std): """ Adds a normal distribution to the Distributions block @ In, xml, xml.etree.ElementTree.Element, Simulation node from template @ In, varName, str, name of variable for whom distribution is being created @ In, mean, float, desired mean of distribution @ In, std, float, desired standard deviation of distribution @ Out, None """ dist = xmlUtils.newNode( 'Normal', attrib={ 'name': self.namingTemplates['distribution'].format(var=varName) }) dist.append(xmlUtils.newNode('mean', text=str(float(mean)))) dist.append(xmlUtils.newNode('sigma', text=str(float(std)))) xml.find('Distributions').append(dist)
def _assemblerNode(self, tag, cls, typ, name): """ Constructs an Assembler-type node given the parameters. e.g. <SolutionExport class='DataObjects' type='DataSet'>export</SolutionExport> @ In, tag, str, name of node @ In, cls, str, name of RAVEN class @ In, typ, str, name of RAVEN class's type @ In, name, str, RAVEN name of object @ Out, node, xml.etree.ElementTree.Element, element formatted RAVEN style. """ attrib = {'class': cls, 'type': typ} node = xmlUtils.newNode(tag, attrib=attrib, text=name) return node
def writeXML(self, writeTo, targets=None, skip=None): """ Allows the SVE to put whatever it wants into an XML to print to file. Overload in subclasses. @ In, writeTo, xmlUtils.StaticXmlElement, entity to write to @ In, targets, list, optional, unused (kept for compatability) @ In, skip, list, optional, unused (kept for compatability) @ Out, None """ root = writeTo.getRoot() for algo in self.tsaAlgorithms: algoNode = xmlUtils.newNode(algo.name) algo.writeXML(algoNode, self.trainedParams[algo]) root.append(algoNode)
def _findTarg(self,root,target): """ Searches "root" for "target" node and makes it if not found @ In, root, xml.etree.ElementTree.Element, node to search under @ In, target, string, name of target to find @ Out, targ, xml.etree.ElementTree.Element, desired target node """ #find target node targ = xmlUtils.findPath(root,target) #if it doesn't exist, make it and add it if targ is None: targ = xmlUtils.newNode(target) root.append(targ) return targ
def findPivotNode(self,pivotVal): """ Searches pivot nodes for node with value pivotVal, or adds it if it doesn't exist @ In, pivotVal, float, value of pivot to find @ Out, pivotNode, xml.etree.ElementTree.Element, node desired """ #find the right dynamic node self.pivotVals,pivotIndex,pivotVal = utils.getRelativeSortedListEntry(self.pivotVals,pivotVal,tol=1e-10) #check if an insertion was performed if len(self.pivotVals) > len(self.pivotNodes): #create new node pivotNode = xmlUtils.newNode(self.pivotParam, attrib={'value':pivotVal}) self.pivotNodes.insert(pivotIndex,pivotNode) else: pivotNode = self.pivotNodes[pivotIndex] return pivotNode
def _modify_outer_files(self, template, sources): files2 = template.find('Files').find('Input') child = files2 files = template.find('Files') # modify path to inner inner = files.find( 'Input') # TODO assuming it's the first file in the template inner.text = '../inner.xml' # add other files needed by inner (functions, armas, etc) for source in sources: if source.is_type('Function'): # add it to the list of things that have to be transferred files = template.find('Files') src = xmlUtils.newNode('Input', attrib={'name': 'transfers'}, text='../' + source._source) files.append(src)
def addScalar(self,target,name,value,root=None,pivotVal=None): """ Adds a node entry named "name" with value "value" to "target" node, such as <root> <target> <name>value<name> @ In, target, string, target parameter to add node value to @ In, name, string, name of characteristic of target to add @ In, value, string/float/etc, value of characteristic @ In, root, xml.etree.ElementTree.Element, optional, root to add to @ In, pivotVal, float, optional, unused (for consistency with dynamic mode) @ Out, None """ if root is None: root = self.tree.getroot() #note: illegal unicode characters are checked for in xmlUtils methods targ = self._findTarg(root,target) targ.append(xmlUtils.newNode(name,text=value))
def addChildren(xNode,tNode): """ Adds children of tnode to xnode, translating @ In, xnode, xml.etree.ElementTree.Element, xml node @ In, tnode, Node, tree structure node @ Out, None """ for child in tNode: #TODO case: comment for comment in child.comments: if comment is not None and len(comment.strip())>0: #append comments before children xNode.append(ET.Comment(comment)) if child.text is None: child.text = '' childNode = xmlUtils.newNode(child.tag,text=child.text,attrib=child.attrib) xNode.append(childNode) addChildren(childNode,child)
def _modify_outer_models(self, template, components): """ TODO """ raven = template.find('Models').find('Code') # executable raven_exec = raven.find('executable') raven_exec.text = os.path.abspath( os.path.join(RAVEN_LOC, '..', 'raven_framework')) # conversion script conv = raven.find('conversion').find('input') conv.attrib['source'] = '../write_inner.py' # aliases text = 'Samplers|MonteCarlo@name:mc_arma_dispatch|constant@name:{}_capacity' for component in components: name = component.name attribs = {'variable': '{}_capacity'.format(name), 'type': 'input'} new = xmlUtils.newNode('alias', text=text.format(name), attrib=attribs) raven.append(new)
def _modify_cash_Global(self, template, case): discountRate = case._global_econ['DiscountRate'] verbosity = case._global_econ['verbosity'] inflation = case._global_econ['inflation'] tax = case._global_econ['tax'] indicator = case._global_econ['Indicator'] try: projectTime = case._global_econ['ProjectTime'] except KeyError: pass template.attrib['verbosity'] = str(verbosity) cash_global = template.find('Global') cash_global.find('DiscountRate').text = str(discountRate) cash_global.find('tax').text = str(tax) cash_global.find('inflation').text = str(inflation) cash_global.find('Indicator').attrib['name'] = indicator['name'][0] cash_global.find('Indicator').text = '\n '.join( indicator['active'][:]) if projectTime: cash_global.append( xmlUtils.newNode('ProjectTime', text=str(projectTime)))
def inputTreeToXml(ts, fromNode=False): """ Converts InputTree into XML @ In, ts, InputTree, tree to convert @ In, fromNode, bool, if True means input is a node instead of a tree @ Out, xTree, xml.etree.ElementTree.ElementTree, tree in xml style """ if fromNode: tRoot = ts else: tRoot = ts.getroot() xRoot = xmlUtils.newNode(tRoot.tag, tRoot.text, tRoot.attrib) def addChildren(xNode, tNode): """ Adds children of tnode to xnode, translating @ In, xnode, xml.etree.ElementTree.Element, xml node @ In, tnode, Node, tree structure node @ Out, None """ for child in tNode: #TODO case: comment for comment in child.comments: if comment is not None and len(comment.strip()) > 0: #append comments before children xNode.append(ET.Comment(comment)) if child.text is None: child.text = '' childNode = xmlUtils.newNode(child.tag, text=child.text, attrib=child.attrib) xNode.append(childNode) addChildren(childNode, child) #end addChildren addChildren(xRoot, tRoot) if fromNode: return xRoot else: return ET.ElementTree(element=xRoot)
def _create_dataobject(self, dataobjects, typ, name, inputs=None, outputs=None, depends=None): """ Creates a data object candidate to go to base class @ In, template, xml.etree.ElementTreeElement, DataObjects node @ In, typ, str, type of data object @ In, name, str, name of data object @ In, inputs, list(str), optional, input variable names @ In, outputs, list(str), optional, output variable names @ In, depends, dict, optional, time-dependency as {index: [stuff that depends on index]} @ Out, None """ assert typ in ['PointSet', 'HistorySet', 'DataSet'] new = xmlUtils.newNode(typ, attrib={'name': name}) if inputs is not None: new.append(xmlUtils.newNode('Input', text=','.join(inputs))) if outputs is not None: new.append(xmlUtils.newNode('Output', text=','.join(outputs))) # index dependence ## if pointset, you went wrong somewhere if you gave dependencies if typ == 'PointSet': assert depends is None ## if a history set, there better only be one elif typ == 'HistorySet': assert depends is not None assert len(depends) == 1, 'Depends is: {}'.format(depends) opt = xmlUtils.newNode('options') opt.append( xmlUtils.newNode('pivotParameter', text=list(depends.keys())[0])) new.append(opt) ## otherwise, if dataset, follow the dependencies elif typ == 'DataSet': if depends is not None: for index, dep in depends.items(): assert isinstance(dep, list) new.append( xmlUtils.newNode('Index', attrib={'var': index}, text=', '.join(dep))) dataobjects.append(new)
results['pass'] += 1 toRemove = attemptFileClear(prettyFileName, toRemove) else: print('ERROR: Test of "pretty" failed! See', prettyFileName, '(below) vs gold/', prettyFileName) print('( START', prettyFileName, ')') for line in file(prettyFileName, 'r'): print(line[:-1]) #omit newline print('( END', prettyFileName, ')') results['fail'] += 1 # test newNode ### test with tag, text, and multiple attributes node = xmlUtils.newNode('tagname', text="text", attrib={ 'atr1': 'atr1_text', 'atr2': 'atr2_text' }) okay = True #type if type(node) != elemType: okay = False print( 'Test of "newNode" failed! Returned node was not an xml.etree.ElementTree! Instead was:', type(node)) #tag if node.tag != 'tagname': okay = False print( 'ERROR: Test of "newNode" failed! Tag should have been "tagname" but instead was "' + node.tag + '".')
class Template(TemplateBase): """ Template for lcoe sweep opt class This templates the workflow split into sweeping over unit capacities in an OUTER run while optimizing unit dispatch in a INNER run. As designed, the ARMA stochastic noise happens entirely on the INNER, for easier parallelization. """ # dynamic naming templates TemplateBase.addNamingTemplates({ 'jobname': '{case}_{io}', 'stepname': '{action}_{subject}', 'variable': '{unit}_{feature}', 'dispatch': 'Dispatch__{component}__{resource}', 'data object': '{source}_{contents}', 'distribution': '{unit}_{feature}_dist', 'ARMA sampler': '{rom}_sampler', 'lib file': 'heron.lib', # TODO use case name? 'cashfname': '_{component}{cashname}', 're_cash': '_rec_{period}_{driverType}{driverName}' }) # template nodes dist_template = xmlUtils.newNode('Uniform') dist_template.append(xmlUtils.newNode('lowerBound')) dist_template.append(xmlUtils.newNode('upperBound')) var_template = xmlUtils.newNode('variable') var_template.append(xmlUtils.newNode('distribution')) var_template.append( xmlUtils.newNode('grid', attrib={ 'type': 'value', 'construction': 'custom' })) ############ # API # ############ def __init__(self): """ Constructor """ here = os.path.dirname( os.path.abspath(sys.modules[self.__class__.__module__].__file__)) self._template_path = here self._template_inner_path = None self._template_outer_path = None self._template_cash_path = None self._template_cash = None self._template_inner = None self._template_outer = None def loadTemplate(self, filename, path): """ todo """ rel_path = os.path.join(self._template_path, path) self._template_inner_path = os.path.join(rel_path, 'inner.xml') self._template_outer_path = os.path.join(rel_path, 'outer.xml') self._template_cash_path = os.path.join(rel_path, 'cash.xml') self._template_inner, _ = xmlUtils.loadToTree( self._template_inner_path, preserveComments=True) self._template_outer, _ = xmlUtils.loadToTree( self._template_outer_path, preserveComments=True) self._template_cash, _ = xmlUtils.loadToTree(self._template_cash_path, preserveComments=True) def createWorkflow(self, case, components, sources): """ Create workflow XMLs @ In, case, HERON case, case instance for this sim @ In, components, list, HERON component instances for this sim @ In, sources, list, HERON source instances for this sim @ Out, inner, XML Element, root node for inner @ Out, outer, XML Element, root node for outer @ Out, cash, XML Element, root node for cashflow input """ # store pieces self.__case = case self.__components = components self.__sources = sources # load a copy of the template inner = copy.deepcopy(self._template_inner) outer = copy.deepcopy(self._template_outer) cash = copy.deepcopy(self._template_cash) # modify the templates inner = self._modify_inner(inner, case, components, sources) outer = self._modify_outer(outer, case, components, sources) cash = self._modify_cash(cash, case, components, sources) # TODO write other files, like cashflow inputs? return inner, outer, cash
# do we already know the capacity values? if cap.type == 'value': vals = cap.get_values() # is the capacity variable being swept over? if isinstance(vals, list): # make new Distribution, Sampler.Grid.variable dist, samp = self._create_new_sweep_capacity( name, var_name, vals) dists_node.append(dist) samps_node.append(samp) # NOTE assumption (input checked): only one interaction per component # if not being swept, then it's just a fixed value. else: samps_node.append( xmlUtils.newNode('constant', text=vals, attrib={'name': var_name})) else: # this capacity will be evaluated by ARMA/Function, and doesn't need to be added here. pass def _create_new_sweep_capacity(self, comp_name, var_name, capacities): """ for OUTER, creates new distribution and variable for grid sampling """ # distribution dist_name = self.namingTemplates['distribution'].format( unit=comp_name, feature='capacity') dist = copy.deepcopy(self.dist_template) dist.attrib['name'] = dist_name dist.find('lowerBound').text = str(min(capacities)) dist.find('upperBound').text = str(max(capacities)) # sampler variable
def _modify_outer(self, template, components, sources): """ Modifies the "outer" template file @ In, template, xml, file template @ In, components, list, HERON Components @ In, sources, list, HERON Placeholders @ Out, template, xml, modified template """ ################### # RUN INFO # ################### run_info = template.find('RunInfo') case_name = self.get_working_dir( 'outer' ) #self.string_templates['jobname'].format(case=self.name, io='o') ooooooooo # I don't think this gets run! # job name run_info.find('JobName').text = case_name # working dir run_info.find('WorkingDir').text = case_name # TODO sequence, maybe should be modified after STEPS (or part of it) ################### # STEPS # # FIlES # ################### # no ARMA steps, that's all on the inner ################### # VARIABLE GROUPS # ################### var_groups = template.find('VariableGroups') # capacities caps = var_groups[0] caps.text = ', '.join('{}_capacity'.format(x.name) for x in components) # results ## these don't need to be changed, they're fine. ################### # DATA OBJECTS # ################### # thanks to variable groups, we don't really need to adjust these. ################### # MODELS # ################### # aliases raven = template.find('Models').find('Code') text = 'Samplers|MonteCarlo@name:mc_arma|constant@name:{}_capacity' for component in components: name = component.name attribs = {'variable': '{}_capacity'.format(name), 'type': 'input'} new = xmlUtils.newNode('alias', text=text.format(name), attrib=attribs) raven.append(new) # TODO location of RAVEN? We should know globally somehow. ################### # DISTRIBUTIONS # # SAMPLERS # ################### dists_node = template.find('Distributions') samps_node = template.find('Samplers').find('Grid') # number of denoisings ## assumption: first node is the denoises node samps_node.find('constant').text = str(self._num_samples) # add sweep variables to input dist_template = xmlUtils.newNode('Uniform') dist_template.append(xmlUtils.newNode('lowerBound')) dist_template.append(xmlUtils.newNode('upperBound')) var_template = xmlUtils.newNode('variable') var_template.append(xmlUtils.newNode('distribution')) var_template.append( xmlUtils.newNode('grid', attrib={ 'type': 'value', 'construction': 'custom' })) for component in components: interaction = component.get_interaction() # if produces, then its capacity might be flexible # TODO this algorithm does not check for everthing to be swept! Future work could expand it. ## Currently checked: Component.Interaction.Capacity # TODO doesn't test for Components.Demand; maybe the user wants to perturb the demand level? if isinstance(interaction, (Components.Producer, Components.Storage)): # is the capacity variable (being swept over)? name = component.name var_name = self.string_templates['variable'].format( unit=name, feature='capacity') if isinstance(interaction._capacity, list): dist_name = self.string_templates['distribution'].format( unit=name, feature='capacity') new = copy.deepcopy(dist_template) new.attrib['name'] = dist_name new.find('lowerBound').text = str( min(interaction._capacity)) new.find('upperBound').text = str( max(interaction._capacity)) dists_node.append(new) # also mess with the Sampler block new = copy.deepcopy(var_template) new.attrib['name'] = var_name new.find('distribution').text = dist_name new.find('grid').text = ', '.join( str(x) for x in sorted(interaction._capacity)) samps_node.append(new) # TODO assumption (input checked): only one interaction per component # elif the capacity is fixed, it becomes a constant else: samps_node.append( xmlUtils.newNode('constant', text=interaction._capacity, attrib={'name': var_name})) ################### # OUTSTREAMS # ################### # no changes needed here! # TODO copy needed model/ARMA/etc files to Outer Working Dir so they're known return template
def _modify_inner(self, template, components, sources): """ Modifies the "inner" template file @ In, template, xml, file template @ In, components, list, HERON Components @ In, sources, list, HERON Placeholders @ Out, template, xml, modified template """ ################### # RUN INFO # # STEPS # ################### run_info = template.find('RunInfo') steps = template.find('Steps') models = template.find('Models') # case, working dir case_name = self.get_working_dir( 'inner' ) #self.string_templates['jobname'].format(case=self.name, io='i') run_info.find('JobName').text = case_name run_info.find('WorkingDir').text = case_name # steps ## for now, just load all sources ## TODO someday, only load what's needed for source in sources: name = source.name if isinstance(source, Placeholders.ARMA): # add a model block models.append( xmlUtils.newNode('ROM', attrib={ 'name': name, 'subType': 'pickledROM' })) # add a read step read_step_name = self.string_templates['stepname'].format( action='read', subject=name) new_step = xmlUtils.newNode('IOStep', attrib={'name': read_step_name}) new_step.append( xmlUtils.newNode('Input', attrib={ 'class': 'Files', 'type': '' }, text=source._source)) new_step.append( xmlUtils.newNode('Output', attrib={ 'class': 'Models', 'type': 'ROM' }, text=name)) # add a sample step (sample #denoises) # add a custom sampler to read the samples ## sequence # NOTE order matters! seq = run_info.find('Sequence').text if seq is None: run_info.find('Sequence').text = read_step_name else: run_info.find('Sequence').text = '{}, {}'.format( seq, read_step_name) # TODO ensemble model? data object? steps.append(new_step) elif isinstance(source, Placeholders.CSV): # add a File # add a step to read # add a data object to read into ## TODO no one needs this right now, so forget it. pass # TODO elif isinstance(source, Placeholders.Function): pass # TODO return template
def _modifyVariables(self, template, var, distData): """ Modifies template for the requested variable @ In, template, xml.etree.ElementTree.Element, root of template XML @ In, var, string, one of the variable names @ In, distData, dict, distribution information (or None if none given) @ Out, template, xml.etree.ElementTree.Element, modified template """ # if distribution data is None, replace it with the default constant value if distData is None: distData = { 'dist': 'constant', 'value': self.varDefaultValues[var] } # modify the Distributions distributions = template.find('Distributions') if distData['dist'] == 'uniform': name = self.namingTemplates['distribution'].format(var=var) lower = distData['lowerBound'] upper = distData['upperBound'] distNode = xmlUtils.newNode('Uniform', attrib={'name': name}) distNode.append(xmlUtils.newNode('lowerBound', text=lower)) distNode.append(xmlUtils.newNode('upperBound', text=upper)) distributions.append(distNode) elif distData['dist'] == 'normal': name = self.namingTemplates['distribution'].format(var=var) mean = distData['mean'] sigma = distData['std'] lower = distData.get('lowerBound', None) upper = distData.get('upperBound', None) distNode = xmlUtils.newNode('Normal', attrib={'name': name}) distNode.append(xmlUtils.newNode('mean', text=mean)) distNode.append(xmlUtils.newNode('sigma', text=sigma)) if lower is not None: distNode.append(xmlUtils.newNode('lowerBound', text=lower)) if upper is not None: distNode.append(xmlUtils.newNode('upperBound', text=upper)) distributions.append(distNode) else: pass # no distribution needed for Constant variables # modify Sampler sampler = template.find('Samplers').find('MonteCarlo') if distData['dist'] == 'constant': sampler.append( xmlUtils.newNode('constant', attrib={'name': var}, text=distData['value'])) else: varNode = xmlUtils.newNode('variable', attrib={'name': var}) varNode.append( xmlUtils.newNode( 'distribution', text=self.namingTemplates['distribution'].format(var=var))) sampler.append(varNode) return template