Commit 309967f6 authored by W. Trevor King's avatar W. Trevor King
Browse files

Implement the folder records and filesystem reconstruction.

parent 810a1a1a
......@@ -9,8 +9,13 @@ from .util import need_to_reorder_bytes as _need_to_reorder_bytes
from .record import RECORD_TYPE as _RECORD_TYPE
from .record.base import UnknownRecord as _UnknownRecord
from .record.base import UnusedRecord as _UnusedRecord
from .record.folder import FolderStartRecord as _FolderStartRecord
from .record.folder import FolderEndRecord as _FolderEndRecord
from .record.variables import VariablesRecord as _VariablesRecord
from .record.wave import WaveRecord as _WaveRecord
# From PTN003:
# Igor writes other kinds of records in a packed experiment file, for
# storing things like pictures, page setup records, and miscellaneous
# settings. The format for these records is quite complex and is not
......@@ -66,5 +71,59 @@ def load(filename, strict=True, ignore_unknown=True):
if not hasattr(filename, 'read'):
f.close()
return records
# From PTN003:
"""The name must be a valid Igor data folder name. See Object
Names in the Igor Reference help file for name rules.
When Igor Pro reads the data folder start record, it creates a new
data folder with the specified name. Any subsequent variable, wave
or data folder start records cause Igor to create data objects in
this new data folder, until Igor Pro reads a corresponding data
folder end record."""
# From the Igor Manual, chapter 2, section 8, page II-123
# http://www.wavemetrics.net/doc/igorman/II-08%20Data%20Folders.pdf
"""Like the Macintosh file system, Igor Pro's data folders use the
colon character (:) to separate components of a path to an
object. This is analogous to Unix which uses / and Windows which
uses \. (Reminder: Igor's data folders exist wholly in memory
while an experiment is open. It is not a disk file system!)
A data folder named "root" always exists and contains all other
data folders.
"""
# From the Igor Manual, chapter 4, page IV-2
# http://www.wavemetrics.net/doc/igorman/IV-01%20Commands.pdf
"""For waves and data folders only, you can also use "liberal"
names. Liberal names can include almost any character, including
spaces and dots (see Liberal Object Names on page III-415 for
details).
"""
# From the Igor Manual, chapter 3, section 16, page III-416
# http://www.wavemetrics.net/doc/igorman/III-16%20Miscellany.pdf
"""Liberal names have the same rules as standard names except you
may use any character except control characters and the following:
" ' : ;
"""
filesystem = {'root': {}}
dir_stack = [('root', filesystem['root'])]
for record in records:
cwd = dir_stack[-1][-1]
if isinstance(record, _FolderStartRecord):
name = record.null_terminated_text
cwd[name] = {}
dir_stack.append((name, cwd[name]))
elif isinstance(record, _FolderEndRecord):
dir_stack.pop()
elif isinstance(record, (_VariablesRecord, _WaveRecord)):
if isinstance(record, _VariablesRecord):
filename = ':variables' # start with an invalid character
else: # to avoid collisions with folder
filename = ':waves' # names
if filename in cwd:
cwd[filename].append(record)
else:
cwd[filename] = [record]
return (records, filesystem)
......@@ -33,3 +33,4 @@ class TextRecord (Record):
def __init__(self, *args, **kwargs):
super(TextRecord, self).__init__(*args, **kwargs)
self.text = str(self.data).replace('\r\n', '\n').replace('\r', '\n')
self.null_terminated_text = self.text.split('\x00', 1)[0]
# Copyright
from .base import Record
from .base import TextRecord
class FolderStartRecord (Record):
class FolderStartRecord (TextRecord):
pass
class FolderEndRecord (Record):
class FolderEndRecord (TextRecord):
pass
......@@ -1248,9 +1248,9 @@ record 39:
'whpad3': 0,
'whpad4': 0})
record 40:
<FolderStartRecord ...>
'Packages'
record 41:
<FolderStartRecord ...>
'WMDataBase'
record 42:
{'header': {'numSysVars': 21,
'numUserStrs': 6,
......@@ -1267,9 +1267,9 @@ record 42:
'u_str': '2'},
'userVars': {}}
record 43:
<FolderEndRecord ...>
''
record 44:
<FolderStartRecord ...>
'PolarGraphs'
record 45:
{'header': {'numSysVars': 21,
'numUserStrs': 10,
......@@ -1317,15 +1317,28 @@ record 45:
'u_y1': 42.732577139459856,
'u_y2': 45.081649278814126}}
record 46:
<FolderEndRecord ...>
''
record 47:
<FolderEndRecord ...>
''
record 48:
'| Platform=Windows95, IGORVersion=3.130\n\n\n\nMoveWindow/P 5.25,40.25,504.75,335\n...hook=PolarWindowHook\nEndMacro\n'
record 49:
''
record 50:
'#include <Polar Graphs> version >= 3.0\n'
<BLANKLINE>
filesystem:
{'root': {':variables': [<VariablesRecord ...>],
':waves': [<WaveRecord ...>,
<WaveRecord ...>,
<WaveRecord ...>,
<WaveRecord ...>,
<WaveRecord ...>,
<WaveRecord ...>,
<WaveRecord ...>,
<WaveRecord ...>],
'Packages': {'PolarGraphs': {':variables': [<VariablesRecord ...>]},
'WMDataBase': {':variables': [<VariablesRecord ...>]}}}}
"""
import os.path
......@@ -1335,6 +1348,7 @@ import sys
from igor.binarywave import load as loadibw
from igor.packed import load as loadpxp
from igor.record.base import TextRecord
from igor.record.folder import FolderStartRecord, FolderEndRecord
from igor.record.variables import VariablesRecord
from igor.record.wave import WaveRecord
......@@ -1353,10 +1367,12 @@ def dumpibw(filename, strict=True):
def dumppxp(filename, strict=True):
sys.stderr.write('Testing {}\n'.format(filename))
path = os.path.join(_data_dir, filename)
records = loadpxp(path, strict=strict)
records,filesystem = loadpxp(path, strict=strict)
for i,record in enumerate(records):
print('record {}:'.format(i))
if isinstance(record, TextRecord):
if isinstance(record, (FolderStartRecord, FolderEndRecord)):
pprint(record.null_terminated_text)
elif isinstance(record, TextRecord):
pprint(record.text)
elif isinstance(record, VariablesRecord):
pprint(record.variables)
......@@ -1364,6 +1380,8 @@ def dumppxp(filename, strict=True):
pprint(record.wave)
else:
pprint(record)
print('\nfilesystem:')
pprint(filesystem)
def pprint(data):
lines = pformat(data).splitlines()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment