class_docstr: Class which encapsulates logit of the master.
docstr: Cleans up data about attacks which generated zero images.
code: def cleanup_attacks_with_zero_images(self):
      """Cleans up data about attacks which generated zero images."""
      print_header("Cleaning up attacks which generated 0 images.")
      # find out attack work to cleanup
      self.adv_batches.init_from_datastore()
      self.attack_work.read_all_from_datastore()
      new_attack_work = {}
      affected_adversarial_batches = set()
      for work_id, work in iteritems(self.attack_work.work):
          adv_batch_id = work["output_adversarial_batch_id"]
          img_count_adv_batch = len(
              self.adv_batches.data[adv_batch_id]["images"]
          )
          if (img_count_adv_batch < 100) and (
              work["elapsed_time"] < 500
          ):
              affected_adversarial_batches.add(adv_batch_id)
              new_attack_work[work_id] = dict(work)
              new_attack_work[work_id].update(
                  {
                      "claimed_worker_id": None,
                      "claimed_worker_start_time": None,
                      "is_completed": False,
                      "error": None,
                      "elapsed_time": None,
                  }
              )
      self.attack_work.replace_work(new_attack_work)
      print_header("Changes in attack works:")
      print(self.attack_work)
      # build list of classification batches
      self.class_batches.init_from_datastore()
      affected_class_batches = set()
      for k, v in iteritems(self.class_batches.data):
          if v["adversarial_batch_id"] in affected_adversarial_batches:
              affected_class_batches.add(k)
      # cleanup defense work on affected batches
      self.defense_work.read_all_from_datastore()
      new_defense_work = {}
      for k, v in iteritems(self.defense_work.work):
          if (
              v["output_classification_batch_id"]
              in affected_class_batches
          ):
              new_defense_work[k] = dict(v)
              new_defense_work[k].update(
                  {
                      "claimed_worker_id": None,
                      "claimed_worker_start_time": None,
                      "is_completed": False,
                      "error": None,
                      "elapsed_time": None,
                      "stat_correct": None,
                      "stat_error": None,
                      "stat_target_class": None,
                      "stat_num_images": None,
                  }
              )
      self.defense_work.replace_work(new_defense_work)
      print_header("Changes in defense works:")
      print(self.defense_work)
      print("")
      print(
          "Total number of affected attack work: ",
          len(self.attack_work),
      )
      print(
          "Total number of affected defense work: ",
          len(self.defense_work),
      )
      inp = input_str(
          'Are you sure? (type "yes" without quotes to confirm): '
      )
      if inp != "yes":
          return
      print("Writing attacks work")
      self.attack_work.write_all_to_datastore()
      print("Writing defenses work")
      self.defense_work.write_all_to_datastore()
      print("Done!")
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import argparse
  import collections
  from collections import defaultdict
  import csv
  from io import BytesIO
  import logging
  import os
  import pickle
  import random
  import time
  from six import iteritems
  from six import iterkeys
  from six import itervalues
  from six.moves import input
  import eval_lib
label_desc: Use image node_id 13 for calling the EvaluationMaster obj's underlying member method code with example usage: obj.cleanup_attacks_with_zero_images() without return types