Skip to content

Commit

Permalink
FIX: PR Suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
aksharsarvesh committed Aug 12, 2024
1 parent 803aa8f commit 9a4a723
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 38 deletions.
7 changes: 3 additions & 4 deletions examples/archiver_time_plot/formula_curve_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ def setup_ui(self):
self.chkbx_live.setChecked(True)
self.formula_box = QLineEdit(self)
self.formula_box.setText("f://{A}")
self.ok_button = ok_button = QPushButton("OK", self)
self.ok_button = QPushButton("OK", self)
self.ok_button.clicked.connect(self.set_formula)
self.main_layout.addWidget(self.formula_box)
self.main_layout.addWidget(self.ok_button)
self.main_layout.addWidget(self.chkbx_live)
self.main_layout.addWidget(self.plot)
self.curve = self.plot.addYChannel(
y_channel="ca://XCOR:LI29:302:IACT",
y_channel="ca://MTEST:Float from ’testing_ioc/pydm-testing-ioc",
name="name",
color="red",
yAxisName="Axis",
Expand All @@ -50,13 +50,12 @@ def setup_ui(self):
useArchiveData=True,
liveData=True,
)
ok_button.clicked.connect(self.set_formula)
self.chkbx_live.stateChanged.connect(lambda x: self.set_live(self.curve, self.formula_curve, x))

@staticmethod
def set_live(curve, formula_curve, live):
curve.liveData = live
formula_curve.liveData = False
formula_curve.liveData = live

def set_formula(self):
print("assuming formula is valid, attempting to use formula")
Expand Down
89 changes: 58 additions & 31 deletions pydm/widgets/archiver_time_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from qtpy.QtCore import QObject, QTimer, Property, Signal, Slot
from qtpy.QtGui import QColor
import logging
from math import e, pi, sqrt, log, sin, cos, tan, asin, acos, atan # noqa
from math import * # noqa
from statistics import mean # noqa

# We noqa those two because those functions/vars are useful in eval() but
Expand All @@ -24,6 +24,7 @@
DEFAULT_ARCHIVE_BUFFER_SIZE = 18000
DEFAULT_TIME_SPAN = 3600.0
MIN_TIME_SPAN = 5.0
APPROX_SECONDS_300_YEARS = 10000000000


class ArchivePlotCurveItem(TimePlotCurveItem):
Expand Down Expand Up @@ -387,7 +388,7 @@ def checkFormula(self) -> bool:
"""Confirm that our formula is still valid. Namely, all of the curves we depend on are still in use"""
for pv in self.pvs.keys():
if not self.pvs[pv].exists:
print(pv + " is no longer a valid row name")
logger.warning(pv + " is no longer a valid row name")
# If one of the rows we rely on is gone, not only are we no longer a valid formula,
# but all rows that rely on us are also invalid.
self.exists = False
Expand All @@ -396,7 +397,11 @@ def checkFormula(self) -> bool:

def createTrueFormula(self) -> str:
"""Convert our human-readable formula to something easier to use for the computer, in the background only"""
formula = self.formula[4:]
prefix = "f://"
if not self.formula.startswith(prefix):
logger.warning("Invalid Formula")
return None
formula = self.formula[len(prefix) :]
# custom function to clean up the formula. First thing replace rows with data entries
formula = re.sub(r"{(.+?)}", r'pvValues["\g<1>"]', formula)
formula = re.sub(r"\^", r"**", formula)
Expand Down Expand Up @@ -424,11 +429,16 @@ def evaluate(self) -> None:
self.minx = float("-inf")
self.maxx = float("inf")
formula = self._trueFormula
if not formula:
logger.error("invalid formula")
return

self.archive_data_buffer = np.zeros((2, 0), order="f", dtype=float)
self.data_buffer = np.zeros((2, 0), order="f", dtype=float)
# Reset buffers
self.points_accumulated = 0
self.archive_points_accumulated = 0

# Populate new dictionaries, simply for ease of access and readability
for pv in self.pvs.keys():
pvArchiveData[pv] = self.pvs[pv].archive_data_buffer
Expand All @@ -437,34 +447,46 @@ def evaluate(self) -> None:
# Only want to attempt to draw the curve where we have all required data for it.
self.minx = max(self.pvs[pv].min_archiver_x(), self.minx)
self.maxx = min(self.pvs[pv].max_archiver_x(), self.maxx)

for pv in self.pvs.keys():
pvValues[pv] = pvArchiveData[pv][1][pvIndices[pv]]
while pvIndices[pv] < len(pvArchiveData[pv][0]) - 1 and pvArchiveData[pv][0][pvIndices[pv]] < self.minx:
pvValues[pv] = pvArchiveData[pv][1][pvIndices[pv]]
pvIndices[pv] += 1
pv_archive_times = pvArchiveData[pv][0]
pv_archive_values = pvArchiveData[pv][1]
pv_current_index = pvIndices[pv]
pvValues[pv] = pv_archive_values[pv_current_index]
while pv_current_index < len(pv_archive_times) - 1 and pv_archive_times[pv_current_index] < self.minx:
pvValues[pv] = pv_archive_values[pv_current_index]
pv_current_index += 1
# Shift starting indices for each row to our minimum
x = self.minx
pvIndices[pv] = pv_current_index

current_time = self.minx
while True:
self.archive_points_accumulated += 1
minPV = None
# Find the next x point out of all of our rows.
# Update only that row's value, use the previous value of other rows for calcs.
current_time = 0
min_pv_current_index = 0
for pv in self.pvs.keys():
if minPV is None or pvArchiveData[pv][0][pvIndices[pv]] < pvArchiveData[minPV][0][pvIndices[minPV]]:
pv_archive_times = pvArchiveData[pv][0]
pv_current_index = pvIndices[pv]
if minPV is None or pv_archive_times[pv_current_index] < current_time:
minPV = pv
x = pvArchiveData[pv][0][pvIndices[pv]]
current_time = pv_archive_times[pv_current_index]
min_pv_current_index = pv_current_index

pvValues[minPV] = pvArchiveData[minPV][1][pvIndices[minPV]]
pvValues[minPV] = pvArchiveData[minPV][1][min_pv_current_index]
try:
temp = np.array([[x], [eval(formula)]])
temp = np.array([[current_time], [eval(formula)]])
except ValueError:
print("Evaluate failed (domain errors? unknown function?)")
temp = np.array([[x], [0]])
logger.warning("Evaluate failed (domain errors? unknown function?)")
temp = np.array([[current_time], [0]])
self.archive_data_buffer = np.append(self.archive_data_buffer, temp, axis=1)
pvIndices[minPV] += 1
# If we are out of data for this row, stop!
if pvIndices[minPV] >= len(pvArchiveData[minPV][0]):
break

if self.liveData:
formula = formula.replace("Archive", "Live")
minx = float("-inf")
Expand All @@ -478,26 +500,35 @@ def evaluate(self) -> None:
pvIndices[pv] = 0
minx = max(self.pvs[pv].min_x(), minx)
maxx = min(self.pvs[pv].max_x(), maxx)
# pvLiveData[pv] = np.append(pvLiveData[pv], np.array([[0],[0]]), axis = 1)

for pv in self.pvs.keys():
pvValues[pv] = pvLiveData[pv][1][pvIndices[pv]]
while pvIndices[pv] < len(pvLiveData[pv][0]) - 1 and pvLiveData[pv][0][pvIndices[pv]] < minx:
pvValues[pv] = pvLiveData[pv][1][pvIndices[pv]]
pvIndices[pv] += 1
pv_live_times = pvLiveData[pv][0]
pv_live_values = pvLiveData[pv][1]
pv_current_index = pvIndices[pv]
pvValues[pv] = pv_live_values[pv_current_index]
while pv_current_index < len(pv_live_times) - 1 and pv_live_times[pv_current_index] < minx:
pvValues[pv] = pv_live_values[pv_current_index]
pv_current_index += 1

pvIndices[pv] = pv_current_index
while True:
self.points_accumulated += 1
minPV = None
x = 0
current_time = 0
min_pv_current_index = 0
for pv in self.pvs.keys():
if minPV is None or pvLiveData[pv][0][pvIndices[pv]] < pvLiveData[minPV][0][pvIndices[minPV]]:
pv_live_times = pvLiveData[pv][0]
pv_current_index = pvIndices[pv]
if minPV is None or pv_live_times[pv_current_index] < current_time:
minPV = pv
x = pvLiveData[pv][0][pvIndices[pv]]
pvValues[minPV] = pvLiveData[minPV][1][pvIndices[minPV]]
current_time = pv_live_times[pv_current_index]
min_pv_current_index = pv_current_index
pvValues[minPV] = pvLiveData[minPV][1][min_pv_current_index]
try:
temp = np.array([[x], [eval(formula)]])
temp = np.array([[current_time], [eval(formula)]])
except ValueError:
print("Evaluate failed (domain errors? unknown function?)")
temp = np.array([[x], [0]])
logger.warning("Evaluate failed (domain errors? unknown function?)")
temp = np.array([[current_time], [0]])
self.data_buffer = np.append(self.data_buffer, temp, axis=1)
pvIndices[minPV] += 1
if pvIndices[minPV] >= len(pvLiveData[minPV][0]):
Expand All @@ -513,7 +544,7 @@ def redrawCurve(self, min_x=None, max_x=None) -> None:
# If we are just a constant, then forget about data
# just draw a straight line from 1970 to 300 years or so in the future
y = [eval(self._trueFormula), eval(self._trueFormula)]
x = [0, 10000000000]
x = [0, APPROX_SECONDS_300_YEARS]
# There is a known bug that this won't graph a constant with an x axis
# of between 30 minutes and 1hr 30 minutes in range. Unknown reason
self.setData(y=y, x=x)
Expand Down Expand Up @@ -703,10 +734,6 @@ def requestDataFromArchiver(self, min_x: Optional[float] = None, max_x: Optional
if curve.use_archive_data:
if max_x is None:
max_x = curve.min_x()
# if curve.points_accumulated > 0:
# max_x = curve.data_buffer[0][curve.getBufferSize() - curve.points_accumulated]
# else:
# max_x = self._starting_timestamp
requested_seconds = max_x - min_x
if requested_seconds <= 5:
continue # Avoids noisy requests when first rendering the plot
Expand Down
6 changes: 3 additions & 3 deletions pydm/widgets/archiver_time_plot_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ def get_data(self, column_name: str, curve: BasePlotCurveItem) -> Any:
if curve.formula is None:
return QVariant()
return str(curve.formula)
elif isinstance(curve, ArchivePlotCurveItem):
# We are either a Formula or a PV (for now at leasts)
else:
if curve.address is None:
return QVariant()
return str(curve.address)
else:
print("how did we get here")

elif column_name == "Live Data":
return bool(curve.liveData)
elif column_name == "Archive Data":
Expand Down

0 comments on commit 9a4a723

Please sign in to comment.