]> Creatis software - gdcm.git/blob - Dicts/ParseDict.py
ENH: update the script
[gdcm.git] / Dicts / ParseDict.py
1 #! /usr/bin/env python
2 """
3 Let's write our own python parser to clean up the pdf (after 
4 pdftotext of course). 
5 Instructions: run pdftotext like this:
6
7 $ pdftotext -f 9 -l 81 -raw -nopgbrk 04_06PU.PDF 04_06PU-3.txt
8
9 then run the python parser like this:
10
11 $ python ParseDict.py 04_06PU.txt dicomV3.dic
12 """
13 import re,os
14
15 """
16 PdfTextParser takes as input a text file (produced by pdftotext)
17 and create as output a clean file (ready to be processed) by
18 DicomV3Expander
19 Warning: PdfTextParser does not expand:
20 - (xxxx,xxxx to xxxx) xxxxxxxxxxxx
21 or
22 - (12xx, 3456) comment...
23
24 """
25 class PdfTextParser:
26   # Cstor
27   def __init__(self):
28     self._InputFilename = ''
29     self._OutputFilename = ''
30     self._Infile = 0
31     self._OutLines = []
32     self._PreviousBuffers = []
33
34   def SetInputFileName(self,s):
35     self._InputFilename = s
36
37   def SetOutputFileName(self,s):
38     self._OutputFilename = s
39   
40   # Function returning if s is a comment for sure
41   def IsAComment(self,s):
42     #print s,  len(s)
43     if s == "Tag Name VR VM":
44       return True
45     elif s == "PS 3.6-2003":
46       return True
47     elif s == "PS 3.6-2004":
48       return True
49     patt = re.compile('^Page [0-9]+$') 
50     if( patt.match(s) ):
51       return True
52     return False
53
54   def IsAStartingLine(self,s):
55     patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\) (.*)$') 
56     if( patt.match(s) ):
57       return True
58     return False
59
60   def IsAFullLine(self,s):
61     patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\) (.*) [A-Z][A-Z] [0-9]$')
62     if( patt.match(s) ):
63       return True
64     return False
65
66   # FIXME this function could be avoided...
67   def IsSuspicious(self,s):
68     l = len(s)
69     if l > 80:
70       return True
71     return False
72
73   def AddOutputLine(self,s):
74     assert not self.IsAComment(s)
75     self._OutLines.append(s + '\n')
76
77   def Open(self):
78     self._Infile = file(self._InputFilename, 'r')
79     for line in self._Infile.readlines():
80       line = line[:-1] # remove '\n'
81       if not self.IsAComment( line ):
82         if self.IsAStartingLine(line):
83           #print "Previous buffer:",self._PreviousBuffers
84           previousbuffer = ' '.join(self._PreviousBuffers)
85           if self.IsAStartingLine(previousbuffer):
86             if not self.IsSuspicious(previousbuffer):
87               self.AddOutputLine(previousbuffer)
88             else:
89               # this case should not happen if I were to rewrite the
90               # thing I should be able to clean that
91               #print "Suspicious:", previousbuffer
92               #print "List is:", self._PreviousBuffers
93               s = self._PreviousBuffers[0]
94               if self.IsAFullLine(s):
95                 # That means we have a weird line that does not start
96                 # as usual (xxxx,xxxx) therefore we tried constructing
97                 # a buffer using a the complete previous line...
98                 #print "Full line:", s
99                 self.AddOutputLine(s)
100                 s2 = ' '.join(self._PreviousBuffers[1:])
101                 #print "Other Full line:", s2
102                 self.AddOutputLine(s2)
103               else:
104                 # we have a suspicioulsy long line, so what that could
105                 # happen, let's check:
106                 if self.IsAFullLine(previousbuffer):
107                   self.AddOutputLine(previousbuffer)
108                 else:
109                   # This is the only case where we do not add
110                   # previousbuffer to the _OutLines
111                   print "Suspicious and Not a full line:", s
112           else:
113             if previousbuffer:
114               print "Not a buffer:", previousbuffer
115           # We can clean buffer, since only the case 'suspicious' +
116           # 'Not a full line' has not added buffer to the list
117           self._PreviousBuffers = []
118           # In all cases save the line for potentially growing this line
119           assert not self.IsAComment(line)
120           self._PreviousBuffers.append(line)
121         else:
122           #print "Not a line",line
123           assert not self.IsAComment(line)
124           self._PreviousBuffers.append(line)
125       else:
126         #print "Comment:",line
127         previousbuffer = ' '.join(self._PreviousBuffers)
128         if previousbuffer and self.IsAStartingLine(previousbuffer):
129           #print "This line is added:", previousbuffer
130           self.AddOutputLine( previousbuffer )
131         else:
132           #print "Line is comment:", line
133           print "Buffer is:", previousbuffer
134         # Ok this is a comment we can safely clean the buffer:
135         self._PreviousBuffers = []
136     self.Write()
137
138   def Write(self):
139     outfile = file(self._OutputFilename, 'w')
140     outfile.writelines( self._OutLines )
141     outfile.close()
142     self._Infile.close()
143     
144   # Main function to call for parsing
145   def Parse(self):
146     self.Open()
147
148 """
149 subclass
150 """
151 class UIDParser(PdfTextParser):
152   def IsAStartingLine(self,s):
153     patt = re.compile('^1.2.840.10008.[0-9.]+ (.*)$') 
154     if( patt.match(s) ):
155       return True
156     #print "Is Not:", s
157     return False
158
159   def IsAFullLine(self,s):
160     patt = re.compile('^1.2.840.10008.[0-9.]+ (.*) PS ?[0-9].1?[0-9]$') 
161     if( patt.match(s) ):
162       return True
163     patt = re.compile('^1.2.840.10008.[0-9.]+ (.*) Well-known frame of reference$') 
164     if( patt.match(s) ):
165       return True
166     patt = re.compile('^1.2.840.10008.[0-9.]+ (.*) \\(Retired\\)$') 
167     if( patt.match(s) ):
168       return True
169     return False
170
171   def IsAComment(self,s):
172     if PdfTextParser.IsAComment(self,s):
173       return True
174     # else let's enhance the super class
175     patt = re.compile('^SPM2 (.*) http(.*)$') 
176     if( patt.match(s) ):
177       return True
178     return False
179
180   def AddOutputLine(self,s):
181     if self.IsAFullLine(s):
182       return PdfTextParser.AddOutputLine(self,s)
183     print "Discarding:", s
184
185 class TransferSyntaxParser(UIDParser):
186   def IsAFullLine(self,s):
187     patt = re.compile('^(.*) Transfer Syntax PS ?[0-9].1?[0-9]$') 
188     if patt.match(s):
189       return UIDParser.IsAStartingLine(self,s)
190     print "Not a TS:", s
191     return False
192     
193   
194
195 """
196 This class is meant to expand line like:
197 - (xxxx,xxxx to xxxx) xxxxxxxxxxxx
198 or
199 - (12xx, 3456) comment...
200
201 """
202 class DicomV3Expander:
203   def __init__(self):
204     self._InputFilename = ''
205     self._OutputFilename = ''
206     self._OutLines = []
207
208   def SetInputFileName(self,s):
209     self._InputFilename = s
210
211   def SetOutputFileName(self,s):
212     self._OutputFilename = s
213  
214   # Function to turn into lower case a tag:
215   # ex: (ABCD, EF01) -> (abcd, ef01)
216   def LowerCaseTag(self,s):
217     #print "Before:", s[:-1]
218     patt = re.compile('^(\\([0-9a-fA-F]+,[0-9a-fA-F]+\\))(.*)$')
219     m = patt.match(s)
220     if m:
221       s1 = m.group(1)
222       s2 = m.group(2)
223       return s1.lower() + s2
224     else:
225       print "Impossible case:", s
226       os.sys.exit(1)
227
228   def AddOutputLine(self,s):
229     if s.__class__ == list:
230       for i in s:
231         self._OutLines.append(i + '\n')
232     else:
233       self._OutLines.append(s + '\n')
234
235   # Expand the line approriaetkly and also add it to the
236   # _OutLines list
237   def ExpandLine(self, s):
238     assert s[-1] == '\n'
239     s = s[:-1]  # remove \n
240     list = []
241     if self.NeedToExpansion(s, list):
242       self.AddOutputLine(list) # list != []
243     elif self.NeedXXExpansion(s, list):
244       self.AddOutputLine(list) # list != []
245     else:
246       self.AddOutputLine(self.LowerCaseTag(s))
247
248   # If line is like:
249   # (0020,3100 to 31FF) Source Image Ids RET
250   def NeedToExpansion(self,s, list):
251     patt = re.compile('^\\(([0-9a-fA-F]+),([0-9a-fA-F]+) to ([0-9a-fA-F]+)\\)(.*)$')
252     m = patt.match(s)
253     if m:
254       #print m.groups()
255       gr = m.group(1)
256       el_start = '0x'+m.group(2)
257       el_end = '0x'+m.group(3)
258       for i in range(eval(el_start), eval(el_end)):
259         el = hex(i)[2:]
260         l = '('+gr+','+el+')'+m.group(4)
261         list.append(l)
262       return True
263     return False
264
265   # If line is like:
266   # (50xx,1200) Number of Patient Related Studies IS 1
267   def NeedXXExpansion(self,s,list):
268     patt = re.compile('^\\(([0-9a-fA-F]+)xx,([0-9a-fA-F]+)\\)(.*)$')
269     m = patt.match(s)
270     if m:
271       #print m.groups()
272       gr_start = m.group(1)
273       el = m.group(2)
274       #el_start = '0x'+m.group(2)
275       #el_end = '0x'+m.group(3)
276       start = '0x'+gr_start+'00'
277       end   = '0x'+gr_start+'FF'
278       for i in range(eval(start), eval(end)):
279         gr = hex(i)[2:]
280         l = '('+gr+','+el+')'+m.group(3)
281         #print l
282         list.append(l)
283       return True
284     return False
285
286   def Write(self):
287     outfile = file(self._OutputFilename, 'w')
288     outfile.writelines( self._OutLines )
289     outfile.close()
290
291   def Expand(self):
292     infile = file(self._InputFilename,'r')
293     for line in infile.readlines():
294       # ExpandLine also LowerCase the line
295       self.ExpandLine(line) # l is [1,n] lines
296     self.Write()
297     infile.close()
298
299 if __name__ == "__main__":
300   argc = len(os.sys.argv )
301   if ( argc < 3 ):
302     print "Sorry, wrong list of args"
303     os.sys.exit(1) #error
304
305   inputfilename = os.sys.argv[1]
306   outputfilename = os.sys.argv[2]
307   tempfile = "/tmp/mytemp"
308   """
309   dp = PdfTextParser()
310   dp.SetInputFileName( inputfilename )
311   #dp.SetOutputFileName( outputfilename )
312   dp.SetOutputFileName( tempfile )
313   dp.Parse()
314
315   exp = DicomV3Expander()
316   exp.SetInputFileName( tempfile )
317   exp.SetOutputFileName( outputfilename )
318   exp.Expand()
319   """
320   dp = TransferSyntaxParser()
321   dp.SetInputFileName( inputfilename )
322   dp.SetOutputFileName( outputfilename )
323   dp.Parse()
324
325   #print dp.IsAStartingLine( "(0004,1212) File-set Consistency Flag US 1\n" )