| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- import re
- from typing import Tuple
- def readasc(filename : str) -> Tuple[dict, dict]:
- """
- Reads Siemens ASC ascii-formatted textfile and returns a dictionary
- structure.
- E.g. a[0].b[2][3].c = "string"
- parses into:
- asc['a'][0]['b'][2][3]['c'] = "string"
- Parameters
- ----------
- filename : str
- Filename of the ASC file.
- Returns
- -------
- asc : dict
- Dictionary of ASC part of file.
- extra : dict
- Dictionary of other fields after "ASCCONV END"
- """
-
- asc, extra = {}, {}
-
- # Read asc file and convert it into a dictionary structure
- with open(filename, 'r') as fp:
- end_of_asc = False
-
- for next_line in fp:
- next_line = next_line.strip()
-
- if next_line == '### ASCCONV END ###': # find end of mrProt in the asc file
- end_of_asc = True
-
- if next_line == '' or next_line[0] == '#':
- continue
- # regex wizardry: Matches lines like 'a[0].b[2][3].c = "string" # comment'
- # Note this assumes correct formatting, e.g. does not check whether
- # brackets match.
- match = re.match(r'^\s*([a-zA-Z0-9\[\]\._]+)\s*\=\s*(("[^"]*"|\'[^\']\')|(\d+)|([0-9\.e\-]+))\s*((#|\/\/)(.*))?$', next_line)
-
- if match:
- field_name = match[1]
- # Keep track of where to put the value: base[assign_to] = value
- if end_of_asc:
- base = extra
- else:
- base = asc
- assign_to = None
-
- # Iterate over every segment of the field name
- parts = field_name.split('.')
- for p in parts:
- # Update base so final assignement is like: base[assign_to][p] = value
- if assign_to != None and assign_to not in base:
- base[assign_to] = {}
- if assign_to != None:
- base = base[assign_to]
-
- # Iterate over brackets
- start = p.find('[')
- if start != -1:
- name = p[:start]
- assign_to = name
-
- while start != -1:
- stop = p.find(']', start)
- index = int(p[start+1:stop])
-
- # Update base so final assignement is like: base[assign_to][p][index] = value
- if assign_to not in base:
- base[assign_to] = {}
- base = base[assign_to]
- assign_to = index
-
- start = p.find('[', stop)
- else:
- assign_to = p
- # Depending on which regex section matched we can infer the value type
- if match[3]:
- base[assign_to] = match[3][1:-1]
- elif match[4]:
- base[assign_to] = int(match[4])
- elif match[5]:
- base[assign_to] = float(match[5])
- else:
- raise RuntimeError('This should not be reached')
- elif next_line.find('=') != -1:
- raise RuntimeError(f'Bug: ASC line with an assignment was not parsed correctly: {next_line}')
- return asc, extra
|