docs: def step2(expnums, ccd, version, prefix=None, dry_run=False, default="WCS"):
      """run the actual step2  on the given exp/ccd combo"""
  
      jmp_trans = ['step2ajmp']
      jmp_args = ['step2bjmp']
      matt_args = ['step2matt_jmp']
  
      idx = 0
      for expnum in expnums:
          jmp_args.append(
              storage.get_file(expnum, ccd=ccd, version=version, ext='obj.jmp', prefix=prefix)[0:-8]
          )
          jmp_trans.append(
              storage.get_file(expnum, ccd=ccd, version=version, ext='obj.jmp', prefix=prefix)[0:-8]
          )
          idx += 1
          matt_args.append('-f%d' % idx)
          matt_args.append(
              storage.get_file(expnum, ccd=ccd, version=version, ext='obj.matt', prefix=prefix)[0:-9]
          )
  
      logging.info(util.exec_prog(jmp_trans))
  
      if default == "WCS":
          logging.info(compute_trans(expnums, ccd, version, prefix, default=default))
  
      logging.info(util.exec_prog(jmp_args))
      logging.info(util.exec_prog(matt_args))
  
      ## check that the shifts from step2 are rational
      check_args = ['checktrans']
      if os.access('proc-these-files', os.R_OK):
          os.unlink('proc-these-files')
      ptf = open('proc-these-files', 'w')
      ptf.write("# A dummy file that is created so checktrans could run.\n")
      ptf.write("# Frame FWHM PSF?\n")
      for expnum in expnums:
          filename = os.path.splitext(storage.get_image(expnum, ccd, version=version, prefix=prefix))[0]
          if not os.access(filename + ".bright.psf", os.R_OK):
              os.link(filename + ".bright.jmp", filename + ".bright.psf")
          if not os.access(filename + ".obj.psf", os.R_OK):
              os.link(filename + ".obj.jmp", filename + ".obj.psf")
          ptf.write("{:>19s}{:>10.1f}{:>5s}\n".format(filename,
                                                      _FWHM,
                                                      "NO"))
      ptf.close()
      if os.access('BAD_TRANS', os.F_OK):
          os.unlink('BAD_TRANS')
  
      logging.info(util.exec_prog(check_args))
  
      if os.access('BAD_TRANS', os.F_OK):
          raise OSError(errno.EBADMSG, 'BAD_TRANS')
  
      if os.access('proc-these-files', os.F_OK):
          os.unlink('proc-these-files')
  
      if dry_run:
          return
  
      for expnum in expnums:
          for ext in ['unid.jmp', 'unid.matt', 'trans.jmp']:
              uri = storage.dbimages_uri(expnum, ccd=ccd, version=version, ext=ext, prefix=prefix)
              filename = os.path.basename(uri)
              storage.copy(filename, uri)
  
      return