Skip to content

Commit

Permalink
Moving plotting into the utils folder (#719)
Browse files Browse the repository at this point in the history
  • Loading branch information
john-science committed Jun 17, 2022
1 parent c7ff593 commit 97ba5ee
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 235 deletions.
1 change: 0 additions & 1 deletion armi/bookkeeping/historyTracker.py
Expand Up @@ -72,7 +72,6 @@ def getHistoryParams(self):
from typing import Tuple
import re

from matplotlib import pyplot
import tabulate

from armi import interfaces
Expand Down
19 changes: 9 additions & 10 deletions armi/bookkeeping/newReports.py
Expand Up @@ -443,7 +443,6 @@ class TimeSeries(ReportNode):
Example
-------
>>> series = TimeSeries("Plot of K-effective", "plot", ["k-effective"], "k-eff", "keff.png") # Adding to a plot with k-effective
>>> time = r.p.time # The current time node of the reactor.
>>> data = r.core.p.keff # The parameter k-effective value at that time.
Expand Down Expand Up @@ -497,9 +496,6 @@ def add(self, lineToAddTo, time, data, uncertainty=None):
data value for the point
uncertainty: float
uncertainty associated with the point
"""
self.dataDictionary[lineToAddTo].append((time, data, uncertainty))

Expand All @@ -513,25 +509,26 @@ def plot(self, ymin=None):
ymin: float
The minimum y-value for the graph.
"""

plt.figure()
lowestY = True
for label in self.labels:

points = self.dataDictionary[label]
# want to sort points by first entry in tuple... (so by asscending time stamp...)
# want to sort points by first entry in tuple, so by asscending time stamp
points.sort(key=itemgetter(0))

if ymin is None or not all([ymin > yi for yi in points]):
lowestY = False

lineY = []
timepoints = []
uncertainties = []
for point in points:
# Now points is sorted, collect times, and a data line...

for point in points:
# Now points is sorted, collect times, and a data line
timepoints.append(point[0])
lineY.append(point[1])
uncertainties.append(point[2])

self.dataDictionary[label] = (lineY, timepoints, uncertainties)
if any(uncertainties):
plt.errorbar(
Expand All @@ -542,11 +539,13 @@ def plot(self, ymin=None):
)
else:
plt.plot(timepoints, lineY, ".-", label=label)

plt.xlabel("Time (yr)")
plt.legend()
plt.ylabel(self.yaxis)
plt.grid(color="0.70")
plt.title(self.title + " for {0}".format(self.rName))

if lowestY:
# set ymin all values are greater than it and it exists.
ax = plt.gca()
Expand All @@ -555,12 +554,12 @@ def plot(self, ymin=None):
figName = self.rName + "." + self.fName
plt.savefig(figName)
plt.close()

return figName

def render(self, level, idPrefix="") -> htmltree.HtmlElement:
"""Renders the Timeseries into a graph and places that Image into an html Img tag and returns a div
containing that image and the images caption if it has one stored."""

figName = self.plot()
if self.encode:
img = htmltree.Img(
Expand Down
9 changes: 4 additions & 5 deletions armi/bookkeeping/report/reportInterface.py
Expand Up @@ -18,13 +18,14 @@
"""
import re

from armi import runLog
from armi import interfaces
from armi.utils import directoryChangers
from armi import runLog
from armi.bookkeeping import report
from armi.bookkeeping.report import reportingUtils
from armi.physics import neutronics
from armi.reactor.flags import Flags
from armi.utils import directoryChangers
from armi.utils import reportPlotting

ORDER = interfaces.STACK_ORDER.BEFORE + interfaces.STACK_ORDER.BOOKKEEPING

Expand Down Expand Up @@ -120,11 +121,9 @@ def interactEOL(self):
b = self.o.r.core.getFirstBlock(Flags.FUEL)
b.setAreaFractionsReport()

from armi.bookkeeping import plotting

dbi = self.o.getInterface("database")
buGroups = self.cs["buGroups"]
plotting.plotReactorPerformance(
reportPlotting.plotReactorPerformance(
self.r, dbi, buGroups, extension=self.cs["outputFileExtension"]
)

Expand Down
96 changes: 0 additions & 96 deletions armi/nuclearDataIO/cccc/rtflux.py
Expand Up @@ -34,12 +34,7 @@
RZFLUX
Reads/writes total fluxes from zones
"""
import math

import numpy
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.collections import PatchCollection

from armi.nuclearDataIO import cccc

Expand Down Expand Up @@ -207,94 +202,3 @@ def getFDFluxReader(adjointFlag):
return AtfluxStream
else:
return RtfluxStream


def plotTriangleFlux(
rtfluxData: RtfluxData,
axialZ,
energyGroup,
hexPitch=math.sqrt(3.0),
hexSideSubdivisions=1,
imgFileExt=".png",
):
"""
Plot region total flux for one core-wide axial slice on triangular/hexagonal geometry.
.. warning:: This will run on non-triangular meshes but will look wrong.
Parameters
----------
rtfluxData : RtfluxData object
The RTFLUX/ATFLUX data object containing all read file data.
Alternatively, this could be a FIXSRC file object,
but only if FIXSRC.fixSrc is first renamed FIXSRC.triangleFluxes.
axialZ : int
The DIF3D axial node index of the core-wide slice to plot.
energyGroup : int
The energy group index to plot.
hexPitch: float, optional
The flat-to-flat hexagonal assembly pitch in this core.
By default, it is sqrt(3) so that the triangle edge length is 1 if hexSideSubdivisions=1.
hexSideSubdivisions : int, optional
By default, it is 1 so that the triangle edge length is 1 if hexPitch=sqrt(3).
imgFileExt : str, optional
The image file extension.
"""

triHeightInCm = hexPitch / 2.0 / hexSideSubdivisions
sideLengthInCm = triHeightInCm / (math.sqrt(3.0) / 2.0)
s2InCm = sideLengthInCm / 2.0

vals = rtfluxData.groupFluxes[:, :, axialZ, energyGroup]
patches = []
colorVals = []
for i in range(vals.shape[0]):
for j in range(vals.shape[1]):
flipped = i % 2 # use (i+j)%2 for rectangular meshing
xInCm = s2InCm * (i - j)
yInCm = triHeightInCm * j + sideLengthInCm / 2.0 / math.sqrt(3) * (
1 + flipped
)

flux = vals[i][j]

if flux:

triangle = mpatches.RegularPolygon(
(xInCm, yInCm),
3,
sideLengthInCm / math.sqrt(3),
orientation=math.pi * flipped,
linewidth=0.0,
)

patches.append(triangle)
colorVals.append(flux)

collection = PatchCollection(patches, alpha=1.0, linewidths=(0,), edgecolors="none")
collection.set_array(
numpy.array(colorVals)
) # add color map to this collection ONLY (pins, not ducts)

plt.figure()
ax = plt.gca()
ax.add_collection(collection)
colbar = plt.colorbar(collection)
colbar.set_label("n/s/cm$^3$")
# colbar.set_label('n*cm/s')
plt.ylabel("cm")
plt.xlabel("cm")
ax.autoscale_view()
plt.savefig("RTFLUX-z" + str(axialZ + 1) + "-g" + str(energyGroup + 1) + imgFileExt)
plt.close()


if __name__ == "__main__":
rtflux = RtfluxStream.readBinary("RTFLUX")
plotTriangleFlux(rtflux, axialZ=10, energyGroup=4)
65 changes: 3 additions & 62 deletions armi/nuclearDataIO/xsLibraries.py
Expand Up @@ -19,16 +19,14 @@
cross sections, but are not necessarily intended to be only neutron and gamma data.
"""

import re
import os
import glob

from matplotlib import pyplot
import os
import re

from armi import runLog
from armi.nucDirectory import nuclideBases
from armi.nuclearDataIO.nuclearFileMetadata import NuclideXSMetadata, RegionXSMetadata
from armi.utils import properties
from armi.nucDirectory import nuclideBases

_ISOTXS_EXT = "ISO"

Expand Down Expand Up @@ -550,63 +548,6 @@ def _buildScatterWeights(self, scatterMatrixKey):
scatterWeights[nucName, fromG] = scatterColumn
return scatterWeights

def plotNucXs(
self, nucNames, xsNames, fName=None, label=None, noShow=False, title=None
):
"""
generates a XS plot for a nuclide on the ISOTXS library
nucName : str or list
The nuclides to plot
xsName : str or list
the XS to plot e.g. n,g, n,f, nalph, etc. see xsCollections for actual names.
fName : str, optional
if fName is given, the file will be written rather than plotting to screen
label : str, optional
is an optional label for image legends, useful in ipython sessions.
noShow : bool, optional
Won't finalize plot. Useful for using this to make custom plots.
Examples
--------
>>> l = ISOTXS()
>>> l.plotNucXs('U238NA','fission')
Plot n,g for all xenon and krypton isotopes
>>> f = lambda name: 'XE' in name or 'KR' in name
>>> l.plotNucXs(sorted(filter(f,l.nuclides.keys())),itertools.repeat('nGamma'))
See Also
--------
armi.nucDirectory.nuclide.plotScatterMatrix
"""
# convert all input to lists
if isinstance(nucNames, str):
nucNames = [nucNames]
if isinstance(xsNames, str):
xsNames = [xsNames]

for nucName, xsName in zip(nucNames, xsNames):
nuc = self[nucName]
thisLabel = label or "{0} {1}".format(nucName, xsName)
x = self.neutronEnergyUpperBounds / 1e6
y = nuc.micros[xsName]
pyplot.plot(x, y, "-", label=thisLabel, drawstyle="steps-post")

ax = pyplot.gca()
ax.set_xscale("log")
ax.set_yscale("log")
pyplot.grid(color="0.70")
pyplot.title(title or " microscopic XS from {0}".format(self))
pyplot.xlabel("Energy (MeV)")
pyplot.ylabel("microscopic XS (barns)")
pyplot.legend()
if fName:
pyplot.savefig(fName)
elif not noShow:
pyplot.show()

def purgeFissionProducts(self, r):
"""
Purge the fission products based on the active nuclides within the reactor.
Expand Down
1 change: 0 additions & 1 deletion armi/reactor/blocks.py
Expand Up @@ -25,7 +25,6 @@
import collections
from typing import Optional, Type, Tuple, ClassVar

import matplotlib.pyplot as plt
import numpy

from armi.reactor import composites
Expand Down

0 comments on commit 97ba5ee

Please sign in to comment.