def main():
    # commandline arguments parser
    parser = argparse.ArgumentParser(
            description="Poisson Noise Removal with Multi-scale Variance " + \
                        "Stabling Transform and Wavelet Transform",
            epilog="Version: %s (%s)" % (__version__, __date__))
    parser.add_argument("-l", "--level", dest="level",
            type=int, default=5,
            help="level of the IUWT decomposition")
    parser.add_argument("-r", "--fdr", dest="fdr",
            type=float, default=0.1,
            help="false discovery rate")
    parser.add_argument("-I", "--fdr-independent", dest="fdr_independent",
            action="store_true", default=False,
            help="whether the FDR null hypotheses are independent")
    parser.add_argument("-s", "--start-scale", dest="start_scale",
            type=int, default=1,
            help="which scale to start the denoising (inclusive)")
    parser.add_argument("-e", "--end-scale", dest="end_scale",
            type=int, default=0,
            help="which scale to end the denoising (inclusive)")
    parser.add_argument("-n", "--niter", dest="niter",
            type=int, default=10,
            help="number of iterations for reconstruction")
    parser.add_argument("-v", "--verbose", dest="verbose",
            action="store_true", default=False,
            help="show verbose progress")
    parser.add_argument("-C", "--clobber", dest="clobber",
            action="store_true", default=False,
            help="overwrite output file if exists")
    parser.add_argument("infile", help="input image with Poisson noises")
    parser.add_argument("outfile", help="output denoised image")
    args = parser.parse_args()

    if args.end_scale == 0:
        args.end_scale = args.level

    if args.verbose:
        print("infile: '%s'" % args.infile, file=sys.stderr)
        print("outfile: '%s'" % args.outfile, file=sys.stderr)
        print("level: %d" % args.level, file=sys.stderr)
        print("fdr: %.2f" % args.fdr, file=sys.stderr)
        print("fdr_independent: %s" % args.fdr_independent, file=sys.stderr)
        print("start_scale: %d" % args.start_scale, file=sys.stderr)
        print("end_scale: %d" % args.end_scale, file=sys.stderr)
        print("niter: %d\n" % args.niter, flush=True, file=sys.stderr)

    if not args.clobber and os.path.exists(args.outfile):
        raise OSError("outfile '%s' already exists" % args.outfile)

    imgfits = fits.open(args.infile)
    img = imgfits[0].data
    # Remove Poisson noises
    msvst = IUWT_VST(data=img)
    msvst.decompose(level=args.level, verbose=args.verbose)
    msvst.denoise(fdr=args.fdr, fdr_independent=args.fdr_independent,
            start_scale=args.start_scale, end_scale=args.end_scale,
            verbose=args.verbose)
    msvst.reconstruct(denoised=True, niter=args.niter, verbose=args.verbose)
    img_denoised = msvst.reconstruction
    # Output
    imgfits[0].data = img_denoised
    imgfits[0].header.add_history("%s: Removed Poisson Noises @ %s" % (
                os.path.basename(sys.argv[0]), datetime.utcnow().isoformat()))
    imgfits[0].header.add_history("  TOOL: %s (v%s, %s)" % (
                os.path.basename(sys.argv[0]), __version__, __date__))
    imgfits[0].header.add_history("  PARAM: %s" % " ".join(sys.argv[1:]))
    imgfits.writeto(args.outfile, checksum=True, clobber=args.clobber)