def addCode(self,input,collapsed=False,language=u("python"),**kwargs): self.__addCell(cell_type=u("code"), collapsed=collapsed, input=input, language=text_type(language), outputs=[], **kwargs)
def addCode(self, input, collapsed=False, language=u("python"), **kwargs): self.__addCell(cell_type=u("code"), collapsed=collapsed, input=input, language=text_type(language), outputs=[], **kwargs)
def isClass(self,name): """Checks whether a cell is of a specific class. If a string is passed the string is checked. Otherwise it is assumed that it is a container and the """ try: if isinstance(name,string_types): return name in self[u("metadata")]["pyFoam"]["classes"] else: for n in name: if n in self[u("metadata")]["pyFoam"]["classes"]: return True return False except KeyError: return False
def isClass(self, name): """Checks whether a cell is of a specific class. If a string is passed the string is checked. Otherwise it is assumed that it is a container and the """ try: if isinstance(name, string_types): return name in self[u("metadata")]["pyFoam"]["classes"] else: for n in name: if n in self[u("metadata")]["pyFoam"]["classes"]: return True return False except KeyError: return False
def testMakeDictionaryProxy(self): d=DictProxy() d["b"]=2 d["a"]=1 g=FoamFileGenerator(d) self.assertEqual(str(g),"b 2;\na 1;\n") d=DictProxy() d["a"]=1 d["b"]=2 g=FoamFileGenerator(d) self.assertEqual(str(g),"a 1;\nb 2;\n") d=DictProxy() d[u("a")]=1 d["b"]=u("2") g=FoamFileGenerator(d) self.assertEqual(str(g),"a 1;\nb 2;\n")
def testMakeDictionaryProxy(self): d=DictProxy() d["b"]=2 d["a"]=1 g=FoamFileGenerator(d) self.assertEqual(str(g),"b 2;\na 1;\n") d=DictProxy() d["a"]=1 d["b"]=2 g=FoamFileGenerator(d) self.assertEqual(str(g),"a 1;\nb 2;\n") d=DictProxy() d[u("a")]=1 d["b"]=u("2") g=FoamFileGenerator(d) self.assertEqual(str(g),"a 1;\nb 2;\n")
def changePython(pythonName, appClass, options=None): options = [] if options is None else options print_("Executing", appClass, "with", pythonName, "trough a proxy-script", "options:", " ".join(options)) if path.exists(pythonName): pyInterpreter = pythonName else: pyInterpreter = which(pythonName) if pyInterpreter is None: print_("Error: No interpreter", pythonName, "found") sys.exit(-1) else: pyInterpreter = pyInterpreter.strip() printDebug("Using interpreter", pyInterpreter) pyFoamLocation = path.dirname(path.dirname(path.dirname(__file__))) printDebug("PyFoam location", pyFoamLocation, ".") if "PYTHONPATH" in env: printDebug("PYTHONPATH:", env["PYTHONPATH"]) else: printDebug("No PYTHONPATH") if "PYTHONPATH" not in env: env["PYTHONPATH"] = pyFoamLocation elif pyFoamLocation not in env["PYTHONPATH"].split(path.pathsep): env["PYTHONPATH"] = pyFoamLocation + path.pathsep + env["PYTHONPATH"] if "PYTHONPATH" in env: printDebug("PYTHONPATH:", env["PYTHONPATH"]) else: printDebug("No PYTHONPATH") scriptFD, scriptName = mkstemp(suffix=".py", prefix="pyFoam" + appClass + "_", text=True) printDebug("Script file:", scriptName, "Handle", scriptFD) os.chmod(scriptName, stat.S_IXUSR | os.stat(scriptName).st_mode) fopen(scriptFD, "w").write( u( """#! %(pyInterpreter)s from PyFoam.Applications.%(appClass)s import %(appClass)s %(appClass)s() """ % { 'appClass': appClass, 'pyInterpreter': " ".join([pyInterpreter] + options) })) ret = call([scriptName] + sys.argv[1:]) printDebug("Return code:", ret) if ret: print_("Error: Return code ", ret, "executing", scriptName) else: os.unlink(scriptName)
def testMakeList(self): g=FoamFileGenerator([1,2,3,4]) self.assertEqual(str(g),"(\n 1\n 2\n 3\n 4\n)\n") g=FoamFileGenerator([1,2,3]) self.assertEqual(str(g),"(1 2 3)") g=FoamFileGenerator(list(range(9))) self.assertEqual(str(g),"(0 1 2 3 4 5 6 7 8)") g=FoamFileGenerator(list(range(6))) self.assertEqual(str(g),"(0 1 2 3 4 5)") g=FoamFileGenerator([1,2,[3,4],4]) self.assertEqual(str(g),"(\n 1\n 2\n\n (\n 3\n 4\n )\n 4\n)\n") g=FoamFileGenerator([1,2,[3,4]]) self.assertEqual(str(g),"(\n 1\n 2\n\n (\n 3\n 4\n )\n)\n") g=FoamFileGenerator(["1",u("2")]) self.assertEqual(str(g),"(\n 1\n 2\n)\n")
def testMakePrimitives(self): g=FoamFileGenerator(1) self.assertEqual(str(g),"1") g=FoamFileGenerator("1") self.assertEqual(str(g),"1") g=FoamFileGenerator(u("1")) self.assertEqual(str(g),"1") g=FoamFileGenerator(1.2) self.assertEqual(str(g),"1.2") g=FoamFileGenerator(long(1)) self.assertEqual(str(g),"1") g=FoamFileGenerator(True) self.assertEqual(str(g),"yes") g=FoamFileGenerator(False) self.assertEqual(str(g),"no")
def testMakeList(self): g=FoamFileGenerator([1,2,3,4]) self.assertEqual(str(g),"(\n 1\n 2\n 3\n 4\n)\n") g=FoamFileGenerator([1,2,3]) self.assertEqual(str(g),"(1 2 3)") g=FoamFileGenerator(list(range(9))) self.assertEqual(str(g),"(0 1 2 3 4 5 6 7 8)") g=FoamFileGenerator(list(range(6))) self.assertEqual(str(g),"(0 1 2 3 4 5)") g=FoamFileGenerator([1,2,[3,4],4]) self.assertEqual(str(g),"(\n 1\n 2\n\n (\n 3\n 4\n )\n 4\n)\n") g=FoamFileGenerator([1,2,[3,4]]) self.assertEqual(str(g),"(\n 1\n 2\n\n (\n 3\n 4\n )\n)\n") g=FoamFileGenerator(["1",u("2")]) self.assertEqual(str(g),"(\n 1\n 2\n)\n")
def testMakePrimitives(self): g=FoamFileGenerator(1) self.assertEqual(str(g),"1") g=FoamFileGenerator("1") self.assertEqual(str(g),"1") g=FoamFileGenerator(u("1")) self.assertEqual(str(g),"1") g=FoamFileGenerator(1.2) self.assertEqual(str(g),"1.2") g=FoamFileGenerator(long(1)) self.assertEqual(str(g),"1") g=FoamFileGenerator(True) self.assertEqual(str(g),"yes") g=FoamFileGenerator(False) self.assertEqual(str(g),"no")
def decode(bcipher, privkey, verbose=False): try: chunksize = int(log(privkey.modulus, 256)) outchunk = chunksize + 1 outfmt = '%%0%dx' % (chunksize * 2, ) result = [] for start in range_func(0, len(bcipher), outchunk): bcoded = bcipher[start:start + outchunk] coded = int(hexlify(bcoded), 16) plain = pow(coded, *privkey) chunk = unhexlify((outfmt % plain).encode()) if verbose: print_('Decode:', chunksize, chunk, plain, coded, bcoded) result.append(chunk) return b''.join(result).rstrip(b'\x00').decode('utf-8') except (UnicodeDecodeError, binascii.Error, TypeError) as e: return u(b'Failed decode for' + bcipher)
def __init__(self,classes=(),pyFoam={},**kwargs): dict.__init__(self,deepcopy(kwargs)) if not u("metadata") in self: self[u("metadata")]={} if len(classes)>0 or len(pyFoam)>0: py=deepcopy(pyFoam) if not "pyFoam" in self[u("metadata")]: self[u("metadata")]["pyFoam"]=py else: self[u("metadata")]["pyFoam"].update(py) if len(classes)>0: if isinstance(classes,string_types): self[u("metadata")]["pyFoam"]["classes"]=(classes,) else: cl=deepcopy(classes) self[u("metadata")]["pyFoam"]["classes"]=tuple(cl)
def __init__(self, classes=(), pyFoam={}, **kwargs): dict.__init__(self, deepcopy(kwargs)) if not u("metadata") in self: self[u("metadata")] = {} if len(classes) > 0 or len(pyFoam) > 0: py = deepcopy(pyFoam) if not "pyFoam" in self[u("metadata")]: self[u("metadata")]["pyFoam"] = py else: self[u("metadata")]["pyFoam"].update(py) if len(classes) > 0: if isinstance(classes, string_types): self[u("metadata")]["pyFoam"]["classes"] = (classes, ) else: cl = deepcopy(classes) self[u("metadata")]["pyFoam"]["classes"] = tuple(cl)
def changePython(pythonName,appClass,options=None): options=[] if options is None else options print_("Executing",appClass,"with",pythonName,"trough a proxy-script", "options:"," ".join(options)) if path.exists(pythonName): pyInterpreter=pythonName else: pyInterpreter=which(pythonName) if pyInterpreter is None: print_("Error: No interpreter",pythonName,"found") sys.exit(-1) else: pyInterpreter=pyInterpreter.strip() printDebug("Using interpreter",pyInterpreter) pyFoamLocation=path.dirname(path.dirname(path.dirname(__file__))) printDebug("PyFoam location",pyFoamLocation,".") if "PYTHONPATH" in env: printDebug("PYTHONPATH:",env["PYTHONPATH"]) else: printDebug("No PYTHONPATH") if "PYTHONPATH" not in env: env["PYTHONPATH"]=pyFoamLocation elif pyFoamLocation not in env["PYTHONPATH"].split(path.pathsep): env["PYTHONPATH"]=pyFoamLocation+path.pathsep+env["PYTHONPATH"] if "PYTHONPATH" in env: printDebug("PYTHONPATH:",env["PYTHONPATH"]) else: printDebug("No PYTHONPATH") scriptFD,scriptName=mkstemp(suffix=".py",prefix="pyFoam"+appClass+"_",text=True) printDebug("Script file:",scriptName,"Handle",scriptFD) os.chmod(scriptName,stat.S_IXUSR | os.stat(scriptName).st_mode) fopen(scriptFD,"w").write(u("""#! %(pyInterpreter)s from PyFoam.Applications.%(appClass)s import %(appClass)s %(appClass)s() """ % {'appClass':appClass,'pyInterpreter':" ".join([pyInterpreter]+options)})) ret=call([scriptName]+sys.argv[1:]) printDebug("Return code:",ret) if ret: print_("Error: Return code ",ret,"executing",scriptName) else: os.unlink(scriptName)
def run(self): if self.cmdname in ["create","copy"]: if self.cmdname=="create": dest=self.parser.getArgs()[0] else: dest=self.parser.getArgs()[1] sol=SolutionDirectory(dest, paraviewLink=False, archive=None) fName=path.join(sol.name,path.basename(sol.name)+".ipynb") if self.opts.destinationFile: fName=self.opts.destinationFile if path.isdir(fName): fName=path.join(fName,path.basename(sol.name)) if path.splitext(fName)[1]!=".ipynb": fName+=".ipynb" if self.opts.absolutePath: usedDest=sol.name else: usedDest=path.relpath(sol.name, start=path.dirname(path.abspath( fName))) if path.exists(fName): if not self.opts.forceWrite: self.error("File",fName,"already existing") else: self.warning("Overwriting",fName) nb=Notebook(name=path.basename(sol.name)) nb.pyFoamMetaData()["description"]="Created by "+self.parser.get_prog_name() if self.cmdname=="create": nb.addHeading("Imports and administrative stuff", level=1,classes="heading") if self.opts.developerMode: nb.addMarkdown("This part only needed by developers (reload imports)", classes=("comment","developer")) nb.addCode("%load_ext autoreload",classes="developer") nb.addCode("%autoreload 2",classes="developer") nb.addMarkdown("Make sure that plots are inlined", classes="comment") nb.addCode("%matplotlib inline") if self.opts.additional: nb.addHeading("Additional imports for convenience", level=2,classes=("heading","additional")) nb.addMarkdown("Allow panning and zooming in plots. Slower than regular plotting so for big data you might want to use `mpld3.disable_notebook()` and erase this cell.", classes=("comment","additional")) nb.addCode( """try: import mpld3 mpld3.enable_notebook() except ImportError: print 'No mpld3-library. No interactive plots'""",classes="additional") nb.addMarkdown( """Wrapper with additional functionality to the regular Pandas-`DataFrame`: * `addData()` for adding columns from other data sets (with resampling * `integrals()` and `weightedAverage()`. Also extended `descripe()` that returns this data Most Pandas-operations (like slicing) will return a Pandas-`DataFrame`. By enclosing this in `DataFrame(...)` you can 'add' this functionality to your data. PyFoam operations return this extended `DataFrame` automatically""", classes=("comment","additional")) nb.addCode("from PyFoam.Wrappers.Pandas import PyFoamDataFrame as DataFrame",classes="additional") nb.addHeading("Data storage", level=2,classes=("heading")) nb.addMarkdown("This is the support for permanently storing data into the notebook", classes="comment") nb.addCode("from PyFoam.IPython import storage") nb.addMarkdown("Due to technical problems the next line has to be executed 'by hand' (it will not work poperly if called from `Run All` or similar). When reopening the page the JavaScript-error is normal (it will go away once the cell is executed). Reading can take some time and the next command will appear to 'hang'", classes="comment") nb.addCode("store=storage()") nb.addMarkdown("The next line switches on the behaviour that items specified with `store(name,func)` will be stored permanently in the notebook. Uncomment if you want this behaviour", classes="comment") nb.addCode("# store.autowriteOn()") nb.addMarkdown("The next line switches off the default behaviour that for items specified with `store(name,func)` if `name` is already specified in the permant storage this value is used and `func` is ignored", classes="comment") nb.addCode("# store.autoreadOff()") nb.addHeading("Case data", level=2,classes=("heading")) nb.addMarkdown("This class makes it easy to access case data. Use tab-completion for available methods", classes="comment") nb.addCode("from PyFoam.IPython.Case import Case") nb.addHeading("The Case",classes="heading") v=self.opts.caseVariable nb.addCode("%s=Case('%s')" % (v,usedDest),classes="case", pyFoam={"caseVar":v,"usedDirectory":usedDest, "casePath":sol.name}) if self.opts.caseReport: nb.addHeading("Case Report",level=2, classes=("report","heading")) regions=sorted(sol.getRegions(defaultRegion=True)) namedRegions=[r for r in regions if r!=None] if len(namedRegions)>0: nb.addMarkdown("Contains named regions *"+ ", ".join(namedRegions)+"*", classes=("info","report")) if sol.procNr>0: nb.addMarkdown("Case seems to be decomposed to "+ str(sol.procNr)+" processors", classes=("info","report")) for region in regions: if region==None: level=3 regionStr="" else: nb.addHeading("Region "+region, level=3,classes=("heading","report")) level=4 regionStr="region='%s'," % region nb.addCode("%s.size(%slevel=%d)" % (v,regionStr,level), classes="report") nb.addCode("%s.boundaryConditions(%slevel=%d)" % (v,regionStr,level), classes="report") nb.addCode("%s.dimensions(%slevel=%d)" % (v,regionStr,level), classes="report") nb.addCode("%s.internalField(%slevel=%d)" % (v,regionStr,level), classes="report") if self.opts.longBCs: nb.addCode("%s.longBoundaryConditions(%slevel=%d)" % (regionStr,v,level), classes="report") if sol.procNr>0 and self.opts.parallelReport: nb.addCode("%s.decomposition(%slevel=%d)" % (v,regionStr,level), classes="report") nb.addCode("%s.processorMatrix(%slevel=%d)" % (v,regionStr,level), classes="report") if self.opts.postprocessing: nb.addHeading("Postprocessing data",classes="heading") if len(sol.timelines)>0: nb.addMarkdown("Timelines",classes="info") nb.addCode("%s.sol.timelines" % v,classes="info") if len(sol.samples)>0: nb.addMarkdown("Samples",classes="info") nb.addCode("%s.sol.samples" % v,classes="info") if len(sol.surfaces)>0: nb.addMarkdown("Surfaces",classes="info") nb.addCode("%s.sol.surfaces" % v,classes="info") if len(sol.distributions)>0: nb.addMarkdown("Distributions",classes="info") nb.addCode("%s.sol.distributions" % v,classes="info") if len(sol.pickledData)>0: nb.addMarkdown("Pickled data files",classes="info") nb.addCode("%s.sol.pickledData" % v,classes="info") if len(sol.pickledPlots)>0: nb.addMarkdown("Pickled plot files",classes="info") nb.addCode("%s.sol.pickledPlots" % v,classes="info") if self.opts.selectors: sel=[("timeline",sol.timelines), ("sample",sol.samples), ("distribution",sol.distributions)] for desc,items in sel: if len(items)>0: nb.addHeading(desc.capitalize()+ " selectors",level=3, classes=("heading","selector")) for i in items: nb.addCode("%s.%sSelector('%s')" % (v,desc,i), classes="selector") if len(sol.pickledPlots)>0 or len(sol.pickledData)>0: nb.addHeading("Data selectors",level=3, classes=("heading","selector")) if len(sol.pickledPlots)>0: nb.addCode("%s.pickledPlotSelector()" % v,classes="selector") if len(sol.pickledData)>0: nb.addCode("%s.pickledDataSelector()" % v,classes="selector") nb.addHeading("User evaluations",classes="heading") nb.addMarkdown("Now add your own stuff",classes="comment") elif self.cmdname=="copy": src=self.parser.getArgs()[0] nb=Notebook(src) cnt=0 for c in nb: if c.isClass("case"): cnt+=1 if cnt>1: self.error(src,"has more than one 'case'-cell") py=c.meta()[u("pyFoam")] used=py["usedDirectory"] input=[] changed=False for l in c["input"]: if l.find(used)>=0: input.append(l.replace(used,usedDest)) changed=True else: input.append(l) if not changed: self.warning(used,"not found") py["usedDirectory"]=usedDest py["casePath"]=sol.name c["input"]=input else: self.error("Unimplemented:",self.cmdname) nb.writeToFile(fName) elif self.cmdname=="info": for n in self.parser.getArgs(): print_(n) print_("-"*len(n)) nb=Notebook(n) meta=nb.pyFoamMetaData() try: origin=meta["createdBy"] except KeyError: origin="unknown" try: created=meta["createdTime"] except KeyError: created="unknown" try: created=meta["createdTime"] except KeyError: created="unknown" try: modified=meta["modificationTime"] except KeyError: modified="unknown" print_("Created by",origin,"at",created, "modified",modified) classes={} cases={} nrOutput=0 for c in nb: if "outputs" in c: if len(c["outputs"])>0: nrOutput+=1 try: py=c.meta()[u("pyFoam")] except KeyError: continue try: cl=py["classes"] for c in cl: try: classes[c]+=1 except KeyError: classes[c]=1 except KeyError: pass if "caseVar" in py: try: cases[py["caseVar"]]=py["casePath"] except KeyError: pass print_(len(nb),"cells. Classes:", ", ".join([k+":"+str(classes[k]) for k in sorted(classes.keys())])) print_("Cells with output:",nrOutput) print("Case-Variables:") for k in sorted(cases.keys()): print_(" ",k,":",cases[k]) print_() elif self.cmdname=="clean": nb=Notebook(self.parser.getArgs()[0]) if not self.opts.overwrite and not self.opts.outfile: self.error("Either specify --overwrite or --outfile") if self.opts.overwrite and self.opts.outfile: self.error("Only specify --overwrite or --outfile") if self.opts.outfile: if path.exists(self.opts.outfile): if not self.opts.force: self.error("File",self.opts.outfile,"exists") else: self.warning("Overwriting",self.opts.outfile) else: if path.splitext(self.opts.outfile)[1]!=".ipynb": self.warning("Appending '.ipynb' to",self.opts.outfile) self.opts.outfile+=".ipynb" if self.opts.overwrite: toFile=self.parser.getArgs()[0] else: toFile=self.opts.outfile removeClasses=self.opts.customTags[:] if self.opts.cleanSelector: removeClasses.append("selector") if self.opts.cleanDeveloper: removeClasses.append("developer") if self.opts.cleanHeading: removeClasses.append("heading") if self.opts.cleanComment: removeClasses.append("comment") if self.opts.cleanReport: removeClasses.append("report") if self.opts.cleanInfo: removeClasses.append("info") print_("Cleaning cells tagged with: "+" ".join(sorted(removeClasses))) nb.reset([c for c in nb if not c.isClass(removeClasses)]) if self.opts.cleanOutput: print_("Removing output") for c in nb: if "outputs" in c: c["outputs"]=[] nb.writeToFile(toFile) else: self.error("Unimplemented command",self.cmdname)
def __init__(self,input=None, nbformat=3, nbformat_minor=0, name=None): """:param input: If this is a string then it is interpreted as a filename. Otherwise as a filehandle. If unset then an empty notebook is contructed :param name: name of the notebook. Only used if a new notebook is created """ self.__content={} if input==None: if name==None: error("Specify at least a name") self.__content={ u("metadata") : { u("name"):text_type(name), u("pyFoam") : { u("createdBy") : "pyFoam", u("createdTime") : asctime() } }, u("nbformat") : nbformat, u("nbformat_minor") : nbformat_minor, u("worksheets") : [ { u("cells"):[] } ] } else: if isinstance(input,string_types): fh=open(input) else: fh=input self.__content=json.load(fh) if ("metadata" not in self.__content or "name" not in self.__content["metadata"] or "nbformat" not in self.__content or "worksheets" not in self.__content): error(str(input),"Notebook does not have the expected format") if len(self.__content["worksheets"])>1: warning(str(input),"has more than one worksheet. Only using the first") elif len(self.__content["worksheets"])==0: error(str(input),"has no worksheets") if "cells" not in self.__content["worksheets"][0]: error(str(input),"has no cells") self.reset([Cell(**c) for c in self]) if u("pyFoam") not in self.__content[u("metadata")]: self.__content[u("metadata")][u("pyFoam")]={ u("createdBy") : "other", u("createdTime") : "unknown" }
def __init__(self, input=None, nbformat=3, nbformat_minor=0, name=None): """@param input: If this is a string then it is interpreted as a filename. Otherwise as a filehandle. If unset then an empty notebook is contructed @param name: name of the notebook. Only used if a new notebook is created """ self.__content = {} if input == None: if name == None: error("Specify at least a name") self.__content = { u("metadata"): { u("name"): text_type(name), u("pyFoam"): { u("createdBy"): "pyFoam", u("createdTime"): asctime() } }, u("nbformat"): nbformat, u("nbformat_minor"): nbformat_minor, u("worksheets"): [{ u("cells"): [] }] } else: if isinstance(input, string_types): fh = open(input) else: fh = input self.__content = json.load(fh) if ("metadata" not in self.__content or "name" not in self.__content["metadata"] or "nbformat" not in self.__content or "worksheets" not in self.__content): error(str(input), "Notebook does not have the expected format") if len(self.__content["worksheets"]) > 1: warning(str(input), "has more than one worksheet. Only using the first") elif len(self.__content["worksheets"]) == 0: error(str(input), "has no worksheets") if "cells" not in self.__content["worksheets"][0]: error(str(input), "has no cells") self.reset([Cell(**c) for c in self]) if u("pyFoam") not in self.__content[u("metadata")]: self.__content[u("metadata")][u("pyFoam")] = { u("createdBy"): "other", u("createdTime"): "unknown" }
def meta(self): return self[u("metadata")]
def writeToFile(self, fName): self.__content[u("metadata")][u("pyFoam")][u( "modificationTime")] = asctime() with open(fName, "w") as fh: json.dump(self.__content, fh, indent=1)
def addHeading(self,title,level=1,**kwargs): self.__addCell(cell_type=u("heading"), source=title, level=level, **kwargs)
def addMarkdown(self, text, **kwargs): self.__addCell(cell_type=u("markdown"), source=text, **kwargs)
def addRaw(self, text, **kwargs): self.__addCell(cell_type=u("raw"), source=text, **kwargs)
def addMarkdown(self,text,**kwargs): self.__addCell(cell_type=u("markdown"), source=text, **kwargs)
def addHeading(self, title, level=1, **kwargs): self.__addCell(cell_type=u("heading"), source=title, level=level, **kwargs)
def addRaw(self,text,**kwargs): self.__addCell(cell_type=u("raw"), source=text, **kwargs)
def writeToFile(self,fName): self.__content[u("metadata")][u("pyFoam")][u("modificationTime")]=asctime() with open(fName,"w") as fh: json.dump(self.__content, fh, indent=1)
def meta(self): return self[u("metadata")]