Skip to content

Commit

Permalink
Merge pull request #200 from prjemian/108-specplots-replot
Browse files Browse the repository at this point in the history
specplots: only replot from last scan
  • Loading branch information
prjemian committed Aug 19, 2019
2 parents 3833681 + 395cccf commit dd5b0da
Show file tree
Hide file tree
Showing 9 changed files with 581 additions and 134 deletions.
42 changes: 41 additions & 1 deletion src/spec2nexus/plugins/spec_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ class SPEC_Epoch(ControlLineHandler):
# do NOT add E to scan_attributes_defined

def process(self, buf, sdf_object, *args, **kws):
matches = [
h
for h in sdf_object.headers
if h.raw.strip() == buf.strip()
]
if len(matches) > 0:
# this header exists, nothing to do
return
header = SpecDataFileHeader(buf, parent=sdf_object)
line = buf.splitlines()[0].strip()
if line.find(".") > -1:
Expand Down Expand Up @@ -224,14 +232,46 @@ def process(self, part, sdf, *args, **kws):
else:
header = sdf.headers[-1] # pick the most recent header

matches = [
(k, s)
for k, s in sdf.scans.items()
if s.raw.strip() == part.strip()
]

if len(matches) > 0 and sdf.last_scan is not None:
if sdf.getScan(sdf.last_scan).raw != part:
return

scan = SpecDataFileScan(header, part, parent=sdf)
if sdf.last_scan is not None:
# We know that `part` does not match any existing scan.
# Do the first few lines match (#S and #D in particular)?
# If so, then that scan has been updated with more data.
def beginning(buf):
"return a string with first few lines of buf"
return "\n".join(
[
line
for line in buf.strip().splitlines()[:5]
if line.startswith("#")
]
)

# TODO: replace beginning() with new algorithm
# if new_scan.raw.startswith(last_scan.raw), that's it!

if beginning(part) == beginning(sdf.getScan(sdf.last_scan).raw):
# remove the last scan
del sdf.scans[sdf.last_scan]
sdf.last_scan = None

scan.S = strip_first_word(part.splitlines()[0].strip())
scan.scanNum = scan.S.split()[0]
scan.scanCmd = strip_first_word(scan.S)

if scan.scanNum in sdf.scans:
# Before raising an exception,
# Check for duplicate and create alternate name
# Check for duplicate scan number and create alternate name
# write as "%d.%d" % (scan.scanNum, index+1)
# where index is the lowest integer in
# range(really big) that is not already in use.
Expand Down
70 changes: 60 additions & 10 deletions src/spec2nexus/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,18 @@ class SpecDataFile(object):
.. autosummary::
~update_available
~dissect_file
~read
~getScan
~getScanNumbers
~getScanNumbersChronological
~getMinScanNumber
~getMaxScanNumber
~getFirstScanNumber
~getLastScanNumber
~getMaxScanNumber
~getMinScanNumber
~getScan
~getScanCommands
~getScanNumbers
~getScanNumbersChronological
~read
~refresh
~update_available
"""

Expand All @@ -243,7 +244,7 @@ def __init__(self, filename):
self.readOK = -1
self.last_scan = None
self.mtime = 0
self.num_lines = 0
self.filesize = 0

if filename is not None:
if not os.path.exists(filename):
Expand All @@ -266,8 +267,57 @@ def update_available(self):
Reference file modification time is stored *after*
file is read in :meth:`read()` method.
EXAMPLE USAGE
Open the SPEC data file (example):
sdf = spec.SpecDataFile(filename)
then, monitor (continuing example):
if sdf.update_available:
myLastScan = sdf.last_scan
sdf.read()
plot_scan_and_newer(myLastScan) # new method
myLastScan = sdf.last_scan
.. note: The previous last_scan is reprocessed since
that scan may not have been complete when the file
was read() previously.
"""
same_mtime = self.mtime == os.path.getmtime(self.fileName)
same_size = self.filesize == os.path.getsize(self.fileName)
identical = same_mtime and same_size
return not identical

def refresh(self):
"""
return self.mtime != os.path.getmtime(self.fileName)
update (refresh) the content if the file is updated
returns previous last_scan or None if file not updated
.. caution: previous last_scan must be re-created if updated
After calling :meth:`refresh()`, any client
with an object of the previous last scan
should get a new object with the update data.
EXAMPLE::
scan = sdf.getScan(42)
checkpoint = sdf.refresh()
if checkpoint is not None:
scan = sdf.getScan(checkpoint) # get updates
"""
if self.update_available:
previous_scan = self.last_scan

self.read()
return previous_scan
return None

def _read_file_(self, spec_file_name):
"""Reads a spec data file"""
Expand Down Expand Up @@ -302,7 +352,6 @@ def dissect_file(self):
"""
buf = self._read_file_(self.fileName).splitlines()
self.num_lines = len(buf)

sections, block = [], []

Expand Down Expand Up @@ -343,6 +392,7 @@ def read(self):
self.specFile = self.fileName

self.last_scan = self.getLastScanNumber()
self.filesize = os.path.getsize(self.fileName)
self.mtime = os.path.getmtime(self.fileName)

def getScan(self, scan_number=0):
Expand Down

0 comments on commit dd5b0da

Please sign in to comment.