import csv
import sys

# As a hack to get sorted output, sort input with:
# (head -n 1 multidensity.csv && tail -n +2 multidensity.csv | sort) > multidensity-temp.csv

filename = "/tmp/multidensity-temp.csv"
with open(filename) as f:
    reader = csv.reader(f)
    header = next(reader)
    assert header == ['treatment','variant', 'density', 'bits', 'qps']
    header[1] = 'target'
    header[-2] = 'bytes/doc'
    header[-1] = 'kqps'
    header.append('dq')
    writer = csv.writer(sys.stdout, delimiter= '&')

    header[-1] += "\\\\"
    writer.writerow(header)

    print("\\midrule")
    for row in reader:
        if row[0] == "Rank0":
            row[1] = "N/A"
        elif row[0] == "RankN":
            if row[1] == "0":
                row[1] = "DQ"
            elif row[1] == "1":
                row[1] = "Q"
            elif row[1] == "2":
                row[1] = "D"
        else:
            print("Error: expected Rank0 or RankN treatment")
            assert False


        dq = "{0:.0f}".format(float(row[-1]) / float(row[-2]))
        row.append(dq)

        # convert from qps to kqps.
        row[-2] = "{0:.0f}".format(float(row[-2])/1000)

        row[-3] = "{0:.0f}".format(float(row[-3]))

        row[-1] += "\\\\"
        writer.writerow(row)


@@ -161,16 +161,94 @@
 mp.csv%0A%0A
+# TODO: take this from BitFunnel instead of hardcoding.%0Ainput_size = 1297.97%0A%0A
 filename
@@ -361,16 +361,18 @@
 der)%0A   
+ #
  assert 
@@ -430,24 +430,86 @@
 , 'qps'%5D%0A   
+ assert header == %5B'treatment','density', 'bits', 'qps'%5D%0A    #
  header%5B1%5D =
@@ -540,17 +540,18 @@
  = '
-bytes/doc
+size ratio
 '%0A  
@@ -748,24 +748,26 @@
  reader:%0A   
+ #
      if row%5B
@@ -781,32 +781,33 @@
 Rank0%22:%0A    
+#
         
 row%5B1%5D = %22N/
@@ -786,32 +786,33 @@
 %22:%0A    #        
+ 
 row%5B1%5D = %22N/A%22%0A 
@@ -810,28 +810,30 @@
 = %22N/A%22%0A    
+#
     
+ 
 elif row%5B0%5D 
@@ -843,24 +843,26 @@
 %22RankN%22:%0A   
+ #
          if 
@@ -876,24 +876,25 @@
 == %220%22:%0A    
+#
             
@@ -885,32 +885,33 @@
    #            
+ 
 row%5B1%5D = %22DQ%22%0A  
@@ -907,24 +907,26 @@
 %5D = %22DQ%22%0A   
+ #
          eli
@@ -942,24 +942,25 @@
 == %221%22:%0A    
+#
             
@@ -951,32 +951,33 @@
    #            
+ 
 row%5B1%5D = %22Q%22%0A   
@@ -972,24 +972,26 @@
 1%5D = %22Q%22%0A   
+ #
          eli
@@ -1007,24 +1007,25 @@
 == %222%22:%0A    
+#
             
@@ -1016,32 +1016,33 @@
    #            
+ 
 row%5B1%5D = %22D%22%0A   
@@ -1037,24 +1037,26 @@
 1%5D = %22D%22%0A   
+ #
      else:%0A 
@@ -1053,24 +1053,26 @@
    else:%0A   
+ #
          pri
@@ -1117,24 +1117,26 @@
 atment%22)%0A   
+ #
          ass
@@ -1145,16 +1145,257 @@
 t False%0A
+        if row%5B0%5D == %22ClassicBitsliced%22:%0A            row%5B0%5D = %22BitslicedSignature%22%0A        elif row%5B0%5D == %22PrivateSharedRank0%22:%0A            row%5B0%5D = %22FreqConscious%22%0A        elif row%5B0%5D == %22Optimal%22:%0A            row%5B0%5D = %22GeneralizedBlocked%22%0A
 %0A%0A      
@@ -1475,16 +1475,65 @@
 nd(dq)%0A%0A
+        row%5B-3%5D = str(float(row%5B-3%5D) / 1297.97)%0A%0A
         
@@ -1632,33 +1632,33 @@
  row%5B-3%5D = %22%7B0:.
-0
+2
 f%7D%22.format(float

Switch to size ratio and new multidensity format.