def step(taskName, parameterByName, folderStore, options):
    # Get parameters
    imageName = parameterByName['image name']
    imagePath = folderStore.getImagePath(imageName)
    imageInformation = folderStore.getImageInformation(imageName)
    multispectralImagePath = imageInformation.getMultispectralImagePath()
    multispectralImage = image_store.load(multispectralImagePath)
    scanRatio = float(parameterByName['scan ratio'])
    classifierName = parameterByName['classifier name']
    classifierPath = folderStore.getClassifierPath(classifierName)
    classifierInformation = folderStore.getClassifierInformation(classifierName)
    windowLengthInMeters = classifierInformation.getWindowLengthInMeters()
    panchromaticImagePath = imageInformation.getPanchromaticImagePath()
    positiveLocationPath = imageInformation.getPositiveLocationPath()
    coverageFraction = parameterByName.get('coverage fraction', 1)
    # Record
    targetProbabilityPath = folderStore.fillProbabilityPath(taskName)
    regionPath = targetProbabilityPath + '_region'
    probabilityInformation = {
        'classifier': {
            'name': classifierName,
            'path': classifierPath,
        },
        'parameters': {
            'window length in meters': windowLengthInMeters,
            'scan ratio': scanRatio, 
            'coverage fraction': coverageFraction,
        },
        'probability': {
            'region path': regionPath,
            'image name': imageName,
            'image path': imagePath,
        },
    }
    # Run
    store.saveInformation(targetProbabilityPath, probabilityInformation)
    if not options.is_test:
        # Frame
        xMax = multispectralImage.width
        yMax = multispectralImage.height
        xMargin = int(xMax * (1 - coverageFraction) / 2)
        yMargin = int(yMax * (1 - coverageFraction) / 2)
        regionFrames = [(xMargin, yMargin, xMax - xMargin, yMax - yMargin)]
        regionDataset = region_store.save(regionPath, regionFrames)
        regionDataset.saveShapefile(regionPath, multispectralImage)
        # Scan
        info = classifier.scan(targetProbabilityPath, classifierPath, multispectralImagePath, panchromaticImagePath, scanRatio, regionFrames)
        # Save
        print 'Saving probability matrix as a shapefile...'
        probability_store.saveShapefile(targetProbabilityPath, targetProbabilityPath, multispectralImage, windowLengthInMeters)
        # Evaluate windows
        windowPerformance, wrongPixelCenters, actualPixelPointMachine = evaluation_process.evaluateWindows(targetProbabilityPath, positiveLocationPath, multispectralImagePath, windowLengthInMeters)
        probabilityInformation['performance'] = windowPerformance
        probabilityInformation['performance'].update(info)
    else:
        wrongPixelCenters = []
        windowPixelWidth, windowPixelHeight = multispectralImage.convertGeoDimensionsToPixelDimensions(windowLengthInMeters, windowLengthInMeters)
        actualPixelPointMachine = point_process.PointMachine([], 'INTEGER', windowPixelWidth, windowPixelHeight)
    # Update
    store.saveInformation(targetProbabilityPath, probabilityInformation)
    # Save patch
    patch_process.buildPatchFromScan(wrongPixelCenters, folderStore, taskName, targetProbabilityPath, multispectralImagePath, panchromaticImagePath, actualPixelPointMachine, classifierInformation, options.is_test)
def step(taskName, parameterByName, folderStore, options):
    # Get
    patchCountPerRegion = parameterByName['patch count per region']
    minimumPercentCorrect = parameterByName['minimum percent correct']
    probabilityName = parameterByName['probability name']
    probabilityPath = folderStore.getProbabilityPath(probabilityName)
    probabilityInformation = probability_store.Information(probabilityPath)
    imageName = probabilityInformation.getImageName()
    imageInformation = folderStore.getImageInformation(imageName)
    multispectralImage = imageInformation.getMultispectralImage()
    panchromaticImage = imageInformation.getPanchromaticImage()
    positiveLocationPath = imageInformation.getPositiveLocationPath()
    positiveGeoLocations, spatialReference = point_store.load(positiveLocationPath)
    # If the probability is from scanning the entire image,
    if not probabilityInformation.hasRegionName():
        regionPath = folderStore.getRegionPath(parameterByName['region name'])
    # Get regionDataset
    else:
        regionPath = probabilityInformation.getRegionPath()
    regionInformation = region_store.Information(regionPath)
    regionFrames = regionInformation.getRegionDataset().getRegionFrames()
    regionCount = len(regionFrames)
    testRegionDataset = regionInformation.getTestRegionDataset()
    # Get windowPixelDimensions
    windowLengthInMeters = probabilityInformation.getWindowLengthInMeters()
    windowPixelDimensions = multispectralImage.convertGeoDimensionsToPixelDimensions(windowLengthInMeters, windowLengthInMeters)
    # Get classifierInformation
    classifierPath = probabilityInformation.getClassifierPath()
    classifierInformation = classifier.Information(classifierPath)
    # Record
    information = {
        'patches': {
            'patch count per region': patchCountPerRegion,
            'minimum percent correct': minimumPercentCorrect,
            'probability name': probabilityName,
            'probability path': probabilityPath,
        },
        'windows': {
            'window length in meters': windowLengthInMeters,
            'spatial reference': spatialReference,
        },
    }
    # Set
    targetPatchPath = folderStore.fillPatchPath(taskName)
    targetPatchFolderPath = os.path.dirname(targetPatchPath)
    if not options.is_test:
        # Make pixelPointMachines
        trainingPixelPointMachine = point_process.makePixelPointMachine(classifierInformation.getTrainingDataset().getGeoCenters(), windowLengthInMeters, multispectralImage)
        testPixelPointMachine = point_process.makePixelPointMachine(classifierInformation.getTestDataset().getGeoCenters(), windowLengthInMeters, multispectralImage)
        actualPixelPointMachine = point_process.makePixelPointMachine(positiveGeoLocations, windowLengthInMeters, multispectralImage)
        # Get badRegionFrames
        print 'Finding regions with poor performance...'
        isGoodWindow = actualPixelPointMachine.getPointsInsideWindow
        probabilityPacks = probability_store.load(probabilityPath)
        performances = analyzeRegions(regionFrames, probabilityPacks, isGoodWindow)
        badRegionFrames = [x[0] for x in itertools.izip(regionFrames, performances) if x[1] < minimumPercentCorrect]
        badRegionCount = len(badRegionFrames)
        # Save badRegionFrames
        badRegionDataset = region_store.save(targetPatchPath, badRegionFrames)
        badRegionDataset.saveShapefile(targetPatchPath, multispectralImage)
        # Make patch window centers
        print 'Sampling from regions with poor performance...'
        testPatchPixelCenters = []
        trainingPatchPixelCenters = []
        for regionFrame in badRegionFrames:
            # Load badCenters
            testRegionFrame = testRegionDataset.getFrameInsideFrame(regionFrame)
            regionalTrainingPixelCenters = trainingPixelPointMachine.getPointsInsideFrame(regionFrame)
            regionalTestPixelCenters = testPixelPointMachine.getPointsInsideFrame(testRegionFrame)
            badCenters = regionalTrainingPixelCenters + regionalTestPixelCenters
            # Generate patch window centers
            centerMachine = sample_process.CenterMachine(regionFrame, windowPixelDimensions, badCenters)
            for patchWindowPixelCenter in centerMachine.makeCenters(patchCountPerRegion):
                if point_process.isInsideRegion(patchWindowPixelCenter, testRegionFrame):
                    testPatchPixelCenters.append(patchWindowPixelCenter)
                else:
                    trainingPatchPixelCenters.append(patchWindowPixelCenter)
        # Define
        buildPatch = lambda makePath, pixelCenters: patch_process.buildPatch(makePath(targetPatchFolderPath), pixelCenters, actualPixelPointMachine, multispectralImage, panchromaticImage, windowLengthInMeters)
        # Produce training and test sets
        information['training set'] = buildPatch(sample_process.makeTrainingPath, trainingPatchPixelCenters).getStatistics()
        information['test set'] = buildPatch(sample_process.makeTestPath, testPatchPixelCenters).getStatistics()
        # Record
        information['performance'] = {
            'bad region count': badRegionCount,
            'region count': regionCount,
            'percent correct': (regionCount - badRegionCount) / float(regionCount),
        }
        information['performance by region'] = dict(('%s %s %s %s' % x[0], x[1]) for x in itertools.izip(regionFrames, performances))
    # Save
    store.saveInformation(targetPatchPath, information)