diffbmu
ΒΆ
A script to compute diff between two bmu files.
#!/usr/bin/env python
''' A script to compute diff between two bmu files.
'''
import os
import sys
import logging
logging.basicConfig()
logger = logging.getLogger("diffbmu")
from optparse import OptionParser
import datetime
import Sadppac
from irfpy.util import utc
def diff(lfile, rfile, **kwds):
'''
'''
loader = kwds.get('loader', 'CENA')
logger.debug("Loader = %s" % loader)
fullmd5 = kwds.get('fullmd5', False)
if fullmd5:
col = -1
coldiff = 0
else:
col = 7
coldiff = 25
allshow = kwds.get('allshow', False)
logger.debug('lfile = %s' % lfile)
if not os.path.exists(lfile):
logger.error('!!!! No file exists %s' % lfile)
raise RuntimeError('!!!! No file exists %s' % lfile)
logger.debug('rfile = %s' % rfile)
if not os.path.exists(rfile):
logger.error('!!!! No file exists %s' % rfile)
raise RuntimeError('!!!! No file exists %s' % rfile)
if loader == "CENA":
reader1 = Sadppac.CenaBmuReader()
reader2 = Sadppac.CenaBmuReader()
elif loader == "SWIM":
reader1 = Sadppac.SwimBmuReader()
reader2 = Sadppac.SwimBmuReader()
else:
raise RuntimeError("Loader %s not supported." % (loader))
# Read data
reader1.readFile(lfile)
reader2.readFile(rfile)
packets1 = reader1.getArray()
packets2 = reader2.getArray()
# BMU size check
npac1 = packets1.size()
npac2 = packets2.size()
logger.debug('Number of packet: L=%d R=%d' % (npac1, npac2))
print('### Diff %s %s' % (lfile, rfile))
if npac1 != npac2:
print('!!!! Size differs:')
print('!!!! N=%d %s' % (npac1, lfile))
print('!!!! N=%d %s' % (npac2, rfile))
print('!!!!!!!!!!!!!!!!!!!!!!!!')
else:
if allshow:
print('oooo Size identical:')
print('oooo N=%d %s' % (npac1, lfile))
print('oooo N=%d %s' % (npac2, rfile))
print('oooooooooooooooooooooooo')
# You cannot assume ascending or descending array order.
pacArr1 = [packets1.getPacket(i) for i in range(npac1)]
pacArr2 = [packets2.getPacket(i) for i in range(npac2)]
tlist1 = [utc.convert(pac.getUtc(), datetime.datetime) for pac in pacArr1]
tlist2 = [utc.convert(pac.getUtc(), datetime.datetime) for pac in pacArr2]
mlist1 = [pac.hash() + ' ' for pac in pacArr1]
mlist2 = [pac.hash() + ' ' for pac in pacArr2] # Space is for padding.
# Order should be organized by the left file's index.
# To be compared is time and md5.
idx_match={} # A pair of indexes in mlist1 and mlist2. (1 to X)
for idx, (pac, tim, md5) in enumerate(list(zip(pacArr1, tlist1, mlist1))):
# Check if same md5 is in the right file
# Four cases: 1 to 0 / 1 to 1 / 1 to mul / 0 to 1
# (mul to 1 is not considered.)
idx2 = -1
while True:
try:
# Update the list
idx2 = mlist2.index(md5, idx2+1)
idx2now = idx_match.get(idx, [])
idx2now.append(idx2)
idx_match[idx] = idx2now
except ValueError:
break
# Here, idx2 search should be employed for "0 to 1" case. Not yet implemented.
idx2set = set()
for idx in list(idx_match.keys()):
idx2list = idx_match[idx]
for idx2 in idx2list:
idx2set.add(idx2)
# For printing. Prepare string array first.
output_str = []
# Now printing
for idx in range(npac1):
idx2list = idx_match.get(idx, [])
if len(idx2list) == 0: # 1 to 0
output_str.append(['D ' +
'%04d %s %s | (No value)' % (idx, tlist1[idx].strftime('%FT%T'), mlist1[idx][:col])])
elif len(idx2list) == 1: # 1 to 1
idx2 = idx2list[0]
output_str.append([' ' + '%04d %s %s | %04d %s %s' % (idx, tlist1[idx].strftime('%FT%T'), mlist1[idx][:col], idx2, tlist2[idx2].strftime('%FT%T'), mlist2[idx2][:col])])
else:
idx2 = idx2list[0]
substr = []
substr.append('M ' + '%04d %s %s | %04d %s %s' % (idx, tlist1[idx].strftime('%FT%T'), mlist1[idx][:col], idx2, tlist2[idx2].strftime('%FT%T'), mlist2[idx2][:col]))
for i in range(1, len(idx2list)):
idx2 = idx2list[i]
substr.append('M ' + '%04d' % (idx) + (' ' * (56 - coldiff))+'| %04d %s %s ' %(idx2, tlist2[idx2].strftime('%FT%T'), mlist2[idx2][:col]))
output_str.append(substr)
# Search the place of the 0 to 1 case.
for idx2 in range(npac2):
if not idx2 in idx2set: # idx2 is 0 to 1 corresp. Search the place of pushing
substr_nu=['A ' + '**** (No value)' + (' ' * (44 - coldiff)) + '| %04d %s %s ' %(idx2, tlist2[idx2].strftime('%FT%T'), mlist2[idx2][:col])]
here = False
for istr in range(len(output_str)):
substr = output_str[istr]
for str in substr:
idx_nu = str.find('|') + 2 # Here assuming the format of the ouput. First | followed by space is delimiter, and 4 digit pacnr follows.
try:
idx2_nu = int(str[idx_nu:idx_nu+4])
if idx2_nu == idx2 - 1:
here=True
except ValueError:
pass
if here:
output_str.insert(istr+1, substr_nu)
break
if not here:
output_str.append(substr_nu)
for substr in output_str:
for str in substr:
if str.startswith(' '): # This is 'consistent' packets.
if allshow:
print(str)
else:
print(str)
def main(*argv, **kwds):
usage = "Usage: %prog [options] bmufile1.bmu bmufile2.bmu"
parser = OptionParser(usage)
parser.add_option("-v", action="store_true", dest="verbose",
default=False, help="Verbose mode")
parser.add_option("-s", action="store_true", dest="useswim",
default=False, help="Use SWIM BMU loader (default CENA)")
parser.add_option("-f", action="store_true", dest="fullmd5",
default=False, help="Show full md5 value.")
parser.add_option("-a", action="store_true", dest="allshow",
default=False, help="Show agreed packet too.")
(options, args) = parser.parse_args(*argv[1:])
if options.verbose:
logger.setLevel(logging.DEBUG)
logger.debug("Set verbose mode")
loader="CENA"
if options.useswim:
loader="SWIM"
logger.debug("Loader = %s" % loader)
if len(args) != 2:
parser.error("!!!! Two files should be specified")
diff(args[0], args[1], loader=loader, fullmd5=options.fullmd5, allshow=options.allshow)
if __name__ == '__main__':
main(sys.argv)