code: def analyze_reach_log(log_fname=None, log_str=None):
      
      assert bool(log_fname) ^ bool(log_str), 'Must specify log_fname OR log_str'
      started_patt = re.compile('Starting ([\d]+)')
      # TODO: it might be interesting to get the time it took to read
      # each paper here
      finished_patt = re.compile('Finished ([\d]+)')
  
      def get_content_nums(txt):
          pat = 'Retrieved content for ([\d]+) / ([\d]+) papers to be read'
          res = re.match(pat, txt)
          has_content, total = res.groups() if res else None, None
          return has_content, total
  
      if log_fname:
          with open(log_fname, 'r') as fh:
              log_str = fh.read()
      # has_content, total = get_content_nums(log_str)  # unused
      pmids = {}
      pmids['started'] = started_patt.findall(log_str)
      pmids['finished'] = finished_patt.findall(log_str)
      pmids['not_done'] = set(pmids['started']) - set(pmids['finished'])
      return pmids
docs: Return unifinished PMIDs given a log file name.