Move all the logic from eos graph to gui graph for warp time
Now backend graphs have to be aware of handles used in UI graphs, so why not
This commit is contained in:
@@ -22,18 +22,24 @@ from abc import ABCMeta, abstractmethod
|
||||
from collections import OrderedDict, namedtuple
|
||||
|
||||
|
||||
YDef = namedtuple('YDef', ('handle', 'unit', 'label'))
|
||||
XDef = namedtuple('XDef', ('handle', 'unit', 'label', 'mainInput'))
|
||||
Input = namedtuple('Input', ('handle', 'unit', 'label', 'iconID', 'defaultValue', 'defaultRange', 'mainOnly'))
|
||||
VectorDef = namedtuple('VectorDef', ('lengthHandle', 'lengthUnit', 'angleHandle', 'angleUnit', 'label'))
|
||||
|
||||
|
||||
class Graph(metaclass=ABCMeta):
|
||||
|
||||
# UI stuff
|
||||
views = []
|
||||
yTypes = None
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
Graph.views.append(cls)
|
||||
|
||||
def __init__(self, eosGraph):
|
||||
self._eosGraph = eosGraph
|
||||
self._cache = {}
|
||||
def __init__(self):
|
||||
self._plotCache = {}
|
||||
self._calcCache = {}
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
@@ -84,25 +90,112 @@ class Graph(metaclass=ABCMeta):
|
||||
|
||||
def getPlotPoints(self, mainInput, miscInputs, xSpec, ySpec, fit, tgt=None):
|
||||
try:
|
||||
plotData = self._cache[fit.ID][(ySpec, xSpec)]
|
||||
plotData = self._plotCache[fit.ID][(ySpec, xSpec)]
|
||||
except KeyError:
|
||||
plotData = self._eosGraph.getPlotPoints(mainInput, miscInputs, xSpec, ySpec, fit, tgt)
|
||||
fitCache = self._cache.setdefault(fit.ID, {})
|
||||
plotData = self._calcPlotPoints(mainInput, miscInputs, xSpec, ySpec, fit, tgt)
|
||||
fitCache = self._plotCache.setdefault(fit.ID, {})
|
||||
fitCache[(ySpec, xSpec)] = plotData
|
||||
return plotData
|
||||
|
||||
def clearCache(self, key=None):
|
||||
if key is None:
|
||||
self._cache.clear()
|
||||
elif key in self._cache:
|
||||
del self._cache[key]
|
||||
self._eosGraph.clearCache(key=key)
|
||||
self._plotCache.clear()
|
||||
self._calcCache.clear()
|
||||
if key in self._plotCache:
|
||||
del self._plotCache[key]
|
||||
if key in self._calcCache:
|
||||
del self._calcCache[key]
|
||||
|
||||
# Calculation stuff
|
||||
def _calcPlotPoints(self, mainInput, miscInputs, xSpec, ySpec, fit, tgt):
|
||||
mainInput, miscInputs = self._normalizeParams(mainInput, miscInputs, fit, tgt)
|
||||
mainInput, miscInputs = self._limitParams(mainInput, miscInputs, fit, tgt)
|
||||
xs, ys = self._getPoints(mainInput, miscInputs, xSpec, ySpec, fit, tgt)
|
||||
xs = self._denormalizeValues(xs, xSpec, fit, tgt)
|
||||
ys = self._denormalizeValues(ys, ySpec, fit, tgt)
|
||||
return xs, ys
|
||||
|
||||
YDef = namedtuple('YDef', ('handle', 'unit', 'label'))
|
||||
XDef = namedtuple('XDef', ('handle', 'unit', 'label', 'mainInput'))
|
||||
Input = namedtuple('Input', ('handle', 'unit', 'label', 'iconID', 'defaultValue', 'defaultRange', 'mainOnly'))
|
||||
VectorDef = namedtuple('VectorDef', ('lengthHandle', 'lengthUnit', 'angleHandle', 'angleUnit', 'label'))
|
||||
_normalizers = {}
|
||||
|
||||
def _normalizeParams(self, mainInput, miscInputs, fit, tgt):
|
||||
key = (mainInput.handle, mainInput.unit)
|
||||
if key in self._normalizers:
|
||||
normalizer = self._normalizers[key]
|
||||
newMainInput = (mainInput.handle, tuple(normalizer(v, fit, tgt) for v in mainInput.value))
|
||||
else:
|
||||
newMainInput = (mainInput.handle, mainInput.value)
|
||||
newMiscInputs = []
|
||||
for miscInput in miscInputs:
|
||||
key = (miscInput.handle, miscInput.unit)
|
||||
if key in self._normalizers:
|
||||
normalizer = self._normalizers[key]
|
||||
newMiscInput = (miscInput.handle, normalizer(miscInput.value))
|
||||
else:
|
||||
newMiscInput = (miscInput.handle, miscInput.value)
|
||||
newMiscInputs.append(newMiscInput)
|
||||
return newMainInput, newMiscInputs
|
||||
|
||||
_limiters = {}
|
||||
|
||||
def _limitParams(self, mainInput, miscInputs, fit, tgt):
|
||||
|
||||
def limitToRange(val, limitRange):
|
||||
if val is None:
|
||||
return None
|
||||
val = max(val, min(limitRange))
|
||||
val = min(val, max(limitRange))
|
||||
return val
|
||||
|
||||
mainHandle, mainValue = mainInput
|
||||
if mainHandle in self._limiters:
|
||||
limiter = self._limiters[mainHandle]
|
||||
newMainInput = (mainHandle, tuple(limitToRange(v, limiter(fit, tgt)) for v in mainValue))
|
||||
else:
|
||||
newMainInput = mainInput
|
||||
newMiscInputs = []
|
||||
for miscInput in miscInputs:
|
||||
miscHandle, miscValue = miscInput
|
||||
if miscHandle in self._limiters:
|
||||
limiter = self._limiters[miscHandle]
|
||||
newMiscInput = (miscHandle, limitToRange(miscValue, limiter(fit, tgt)))
|
||||
newMiscInputs.append(newMiscInput)
|
||||
else:
|
||||
newMiscInputs.append(miscInput)
|
||||
return newMainInput, newMiscInputs
|
||||
|
||||
_getters = {}
|
||||
|
||||
def _getPoints(self, mainInput, miscInputs, xSpec, ySpec, fit, tgt):
|
||||
try:
|
||||
getter = self._getters[(xSpec.handle, ySpec.handle)]
|
||||
except KeyError:
|
||||
return [], []
|
||||
else:
|
||||
return getter(self, mainInput, miscInputs, fit, tgt)
|
||||
|
||||
_denormalizers = {}
|
||||
|
||||
def _denormalizeValues(self, values, axisSpec, fit, tgt):
|
||||
key = (axisSpec.handle, axisSpec.unit)
|
||||
if key in self._denormalizers:
|
||||
denormalizer = self._denormalizers[key]
|
||||
values = [denormalizer(v, fit, tgt) for v in values]
|
||||
return values
|
||||
|
||||
def _iterLinear(self, valRange, resolution=100):
|
||||
rangeLow = min(valRange)
|
||||
rangeHigh = max(valRange)
|
||||
# Amount is amount of ranges between points here, not amount of points
|
||||
step = (rangeHigh - rangeLow) / resolution
|
||||
if step == 0:
|
||||
yield rangeLow
|
||||
else:
|
||||
current = rangeLow
|
||||
# Take extra half step to make sure end of range is always included
|
||||
# despite any possible float errors
|
||||
while current <= (rangeHigh + step / 2):
|
||||
yield current
|
||||
current += step
|
||||
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
|
||||
Reference in New Issue
Block a user