exportnow.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. r"""This module is used to export catalyst defined data products directly
  2. within the ParaView GUI."""
  3. from paraview.simple import *
  4. haveCinemaC = True
  5. try:
  6. import paraview.tpl.cinema_python.adaptors.paraview.pv_introspect as pvi
  7. except:
  8. haveCinemaC = False
  9. import os
  10. class CinemaDHelper(object):
  11. """ A helper that we funnel file save commands through so that we can build up a CinemaD table for them. """
  12. def __init__(self, mcd, rd):
  13. self.__EnableCinemaDTable = mcd
  14. self.__RootDirectory = rd
  15. if rd and not rd.endswith("/"):
  16. self.__RootDirectory = rd + "/"
  17. self.Keys = set()
  18. self.Contents = []
  19. self.KeysWritten = None
  20. def __StripRootDir(self, filename):
  21. if self.__RootDirectory:
  22. return filename[filename.startswith(self.__RootDirectory) and len(self.__RootDirectory):]
  23. return filename
  24. def __MakeCinDFileNamesUnderRootDir(self, filename=""):
  25. """ filename wrangling for root directory placement """
  26. indexfilename = 'data.csv'
  27. datafilename = filename
  28. if self.__RootDirectory:
  29. indexfilename = self.__RootDirectory + "data.csv"
  30. # strip leading root directory from filename if present
  31. datafilename = self.__StripRootDir(filename)
  32. return indexfilename, datafilename
  33. def AppendToCinemaDTable(self, time, producer, filename):
  34. """ keep a record of every standard file written out so that we can list it later """
  35. if not self.__EnableCinemaDTable:
  36. return
  37. indexfilename, datafilename = self.__MakeCinDFileNamesUnderRootDir(filename)
  38. self.Keys.add("timestep")
  39. self.Keys.add("producer")
  40. self.Keys.add("FILE")
  41. self.Contents.append({'timestep':time,'producer':producer,'FILE':datafilename})
  42. def AppendCViewToCinemaDTable(self, time, producer, filelist):
  43. """ keep a record of every new file that cinema image writes along with the keys that produced them so that we can list them all later """
  44. if not self.__EnableCinemaDTable or not haveCinemaC:
  45. return
  46. self.Keys.add("timestep")
  47. self.Keys.add("producer")
  48. self.Keys.add("FILE")
  49. #unroll the contents into key lists and filenames
  50. for viewname in filelist:
  51. for entry in filelist[viewname]:
  52. keylist = entry[0]
  53. # avoid redundancy from name change
  54. if 'time' in keylist:
  55. time = keylist['time']
  56. del keylist['time']
  57. for k in keylist:
  58. self.Keys.add(k)
  59. keylist['timestep']=time
  60. keylist['producer']=producer
  61. keylist['FILE']=self.__StripRootDir(entry[1])
  62. self.Contents.append(keylist)
  63. def Finalize(self):
  64. """ Finish off the table and write it to a file """
  65. # this is necessary because we don't really know keys (from cinema image) until the end.
  66. if not self.__EnableCinemaDTable:
  67. return
  68. indexfilename, datafilename = self.__MakeCinDFileNamesUnderRootDir()
  69. if self.__RootDirectory and not os.path.exists(self.__RootDirectory):
  70. os.makedirs(self.__RootDirectory)
  71. f = open(indexfilename, "w")
  72. # write the header line
  73. f.write("timestep,")
  74. f.write("producer,")
  75. for k in self.Keys:
  76. if k != 'timestep' and k != 'producer' and k != 'FILE':
  77. f.write("%s,"%k)
  78. f.write("FILE\n")
  79. # write all of the contents
  80. for l in self.Contents:
  81. f.write("%s,"%l['timestep'])
  82. f.write("%s,"%l['producer'])
  83. for k in self.Keys:
  84. if k != 'timestep' and k != 'producer' and k != 'FILE':
  85. v = ''
  86. if k in l:
  87. v = l[k]
  88. f.write("%s,"%v)
  89. f.write("%s\n"%self.__StripRootDir(l['FILE']))
  90. f.close()
  91. def WriteNow(self):
  92. """ For Catalyst, we don't generally have a Final state, so we call this every CoProcess call and fixup the table if we have to. """
  93. if not self.__EnableCinemaDTable:
  94. return
  95. indexfilename, datafilename = self.__MakeCinDFileNamesUnderRootDir()
  96. if self.KeysWritten == self.Keys:
  97. # phew nothing new, we can just append a record
  98. f = open(indexfilename, "a+")
  99. for l in self.Contents:
  100. f.write("%s,"%l['timestep'])
  101. f.write("%s,"%l['producer'])
  102. for k in self.Keys:
  103. if k != 'timestep' and k != 'producer' and k != 'FILE':
  104. v = ''
  105. if k in l:
  106. v = l[k]
  107. f.write("%s,"%v)
  108. f.write("%s\n"%self.__StripRootDir(l['FILE']))
  109. f.close()
  110. self.Contents = []
  111. return
  112. #dang, whatever we wrote recently had a new variable
  113. #we may have to extend and rewrite the old output file
  114. readKeys = None
  115. readContents = []
  116. if os.path.exists(indexfilename):
  117. #yep we have to do it
  118. #parse the old file
  119. f = open(indexfilename, "r")
  120. for line in f:
  121. read = line[0:-1].split(",") #-1 to skip trailing\n
  122. if readKeys is None:
  123. readKeys = read
  124. else:
  125. entry = {}
  126. for idx in range(0,len(read)):
  127. entry.update({readKeys[idx]:read[idx]})
  128. readContents.append(entry)
  129. #combine contents
  130. if readKeys is not None:
  131. self.Keys = self.Keys.union(readKeys)
  132. readContents.extend(self.Contents)
  133. self.Contents = readContents
  134. #finally, write
  135. self.Finalize()
  136. self.KeysWritten = self.Keys.copy()
  137. self.Contents = []
  138. class __CinemaACHelper(object):
  139. """ Another helper that connects up to cinema_python's export function. """
  140. def __init__(self, rd, vsel, tsel, asel):
  141. self.__RootDirectory = rd
  142. self.__ViewSelection = vsel
  143. self.__TrackSelection = tsel
  144. self.__ArraySelection = asel
  145. self.NewFiles = None
  146. if haveCinemaC:
  147. def ExportNow(self, time):
  148. r = pvi.export_scene(baseDirName=self.__RootDirectory,
  149. viewSelection=dict(self.__ViewSelection),
  150. trackSelection=dict(self.__TrackSelection),
  151. arraySelection=dict(self.__ArraySelection),
  152. forcetime=time)
  153. self.NewFiles = r
  154. else:
  155. def ExportNow(self, time):
  156. pass
  157. def _fixup_and_makedir_if_needed(rootdir):
  158. if rootdir and not rootdir.endswith("/"):
  159. rootdir = rootdir + "/"
  160. if rootdir and not os.path.exists(rootdir):
  161. os.makedirs(rootdir)
  162. return rootdir
  163. def ExportNow(image_root_directory,
  164. data_root_directory,
  165. file_name_padding,
  166. make_cinema_table,
  167. cinema_tracks,
  168. cinema_arrays,
  169. rendering_info):
  170. """The user facing entry point. Here we get a hold of ParaView's animation controls, step through the animation, and export the things we've been asked to be the caller."""
  171. CIND = CinemaDHelper(make_cinema_table, image_root_directory)
  172. image_root_directory = _fixup_and_makedir_if_needed(image_root_directory)
  173. data_root_directory = _fixup_and_makedir_if_needed(data_root_directory)
  174. # get a hold of the scene
  175. spm = servermanager.vtkSMProxyManager.GetProxyManager().GetActiveSessionProxyManager()
  176. ed = spm.GetExportDepot()
  177. s = GetAnimationScene()
  178. s.GoToFirst()
  179. et = s.EndTime
  180. tnow = s.AnimationTime
  181. numTimesteps = len(paraview.simple.GetAnimationScene().TimeKeeper.TimestepValues)
  182. timesteps = {}
  183. # We must perform the export loop at least once, even in the case where
  184. # the input data contains no timesteps
  185. if (numTimesteps == 0):
  186. timesteps = list(range(1))
  187. else:
  188. timesteps = list(range(numTimesteps))
  189. # export loop
  190. for tstep in timesteps:
  191. padded_tstep = str(tstep).rjust(file_name_padding, '0')
  192. helpers = []
  193. # loop through the configured writers and export at the requested times
  194. ed.InitNextWriterProxy()
  195. wp = ed.GetNextWriterProxy()
  196. writercnt = 0
  197. while wp:
  198. freq = wp.GetProperty("WriteFrequency").GetElement(0)
  199. if ((tstep % freq==0) and
  200. (not (wp.GetXMLName() == "Cinema image options"))):
  201. # this isn't pretty. I couldn't find a way to write
  202. # directly with the writer proxy. So what I do here
  203. # is find the input and filename and make a new writer
  204. # to use.
  205. proxyname = spm.GetProxyName("export_writers", wp)
  206. inputname = proxyname[0:proxyname.find("|")]
  207. inputproxy = FindSource(inputname)
  208. if wp.GetProperty("ChooseArraysToWrite").GetElement(0) == 1:
  209. point_arrays = []
  210. cell_arrays = []
  211. arrays_property = wp.GetProperty("PointDataArrays")
  212. for i in range(arrays_property.GetNumberOfElements()):
  213. point_arrays.append(arrays_property.GetElement(i))
  214. arrays_property = wp.GetProperty("CellDataArrays")
  215. for i in range(arrays_property.GetNumberOfElements()):
  216. cell_arrays.append(arrays_property.GetElement(i))
  217. if not point_arrays:
  218. point_arrays = [' ']
  219. if not cell_arrays:
  220. cell_arrays = [' ']
  221. # create a temporary array culling filter
  222. pass_arrays = PassArrays(Input=inputproxy, \
  223. PointDataArrays=point_arrays, CellDataArrays=cell_arrays)
  224. inputproxy = pass_arrays
  225. helpers.append(inputproxy)
  226. fname = wp.GetProperty("CatalystFilePattern").GetElement(0)
  227. if wp.GetXMLName() == "ExodusIIWriter":
  228. fnamefilled = data_root_directory+fname+padded_tstep
  229. else:
  230. fnamefilled = data_root_directory+fname.replace("%t", padded_tstep)
  231. kwargs = {}
  232. DataMode = wp.GetProperty("DataMode")
  233. if DataMode is not None:
  234. kwargs["DataMode"] = wp.GetProperty("DataMode").GetElement(0)
  235. HeaderType = wp.GetProperty("HeaderType")
  236. if HeaderType is not None:
  237. kwargs["HeaderType"] = wp.GetProperty("HeaderType").GetElement(0)
  238. EncodeAppendedData = wp.GetProperty("EncodeAppendedData")
  239. if EncodeAppendedData is not None:
  240. kwargs["EncodeAppendedData"] = wp.GetProperty("EncodeAppendedData").GetElement(0)
  241. CompressorType = wp.GetProperty("CompressorType")
  242. if CompressorType is not None:
  243. kwargs["CompressorType"] = wp.GetProperty("CompressorType").GetElement(0)
  244. CompressionLevel = wp.GetProperty("CompressionLevel")
  245. if CompressionLevel is not None:
  246. kwargs["CompressionLevel"] = wp.GetProperty("CompressionLevel").GetElement(0)
  247. # finally after all of the finageling above, save the data
  248. SaveData(fnamefilled, inputproxy, **kwargs)
  249. # don't forget to tell cinema D about it
  250. CIND.AppendToCinemaDTable(tnow, "writer_%s" % writercnt, fnamefilled)
  251. wp = ed.GetNextWriterProxy()
  252. writercnt = writercnt + 1
  253. # loop through the configured screenshots and export at the requested times
  254. ed.InitNextScreenshotProxy()
  255. ssp = ed.GetNextScreenshotProxy()
  256. viewcnt = 0
  257. while ssp:
  258. if not ssp.HasAnnotation("enabled") or not (ssp.GetAnnotation("enabled") == '1'):
  259. ssp= ed.GetNextScreenshotProxy()
  260. continue
  261. freq = ssp.GetProperty("WriteFrequency").GetElement(0)
  262. if tstep % freq==0:
  263. fname = ssp.GetProperty("CatalystFilePattern").GetElement(0)
  264. if fname.endswith("cdb"):
  265. CINAC = __CinemaACHelper(image_root_directory,
  266. rendering_info,
  267. cinema_tracks,
  268. cinema_arrays)
  269. # special treatment for cinema image data bases
  270. CINAC.ExportNow(tnow)
  271. # don't forget to tell cinema D about it
  272. CIND.AppendCViewToCinemaDTable(tnow, "cview_%s"%viewcnt, CINAC.NewFiles)
  273. else:
  274. fnamefilled = image_root_directory+fname.replace("%t", padded_tstep)
  275. # save the screenshot
  276. ssp.WriteImage(fnamefilled)
  277. # don't forget to tell cinema D about it
  278. CIND.AppendToCinemaDTable(tnow, "view_%s"%viewcnt, fnamefilled)
  279. ssp = ed.GetNextScreenshotProxy()
  280. viewcnt = viewcnt + 1
  281. tstep = tstep + 1
  282. s.GoToNext()
  283. tnow = s.AnimationTime
  284. # destroy array culling filters
  285. for x in helpers:
  286. Delete(x)
  287. # defer actual cinema D output until the end because we only know now what the full set of cinema D columns actually are
  288. CIND.Finalize()