'Test that a Custom Factor computes the correct values when passed a
mask. The mask/filter should be applied prior to computing any values,
as opposed to computing the factor across the entire universe of
assets. Any assets that are filtered out should be filled with missing
values.'

def test_masked_factor(self):

    loader = self.loader
    dates = self.dates[5:8]
    assets = self.assets
    asset_ids = self.asset_ids
    constants = self.constants
    num_dates = len(dates)
    num_assets = len(assets)
    open = USEquityPricing.open
    close = USEquityPricing.close
    engine = SimplePipelineEngine((lambda column: loader), self.dates, self.asset_finder)
    factor1_value = constants[open]
    factor2_value = (3.0 * (constants[open] - constants[close]))
    def create_expected_results(expected_value, mask):
        expected_values = where(mask, expected_value, nan)
        return DataFrame(expected_values, index=dates, columns=assets)
    cascading_mask = (AssetIDPlusDay() < (asset_ids[(-1)] + dates[0].day))
    expected_cascading_mask_result = make_cascading_boolean_array(shape=(num_dates, num_assets))
    alternating_mask = (AssetIDPlusDay() % 2).eq(0)
    expected_alternating_mask_result = make_alternating_boolean_array(shape=(num_dates, num_assets), first_value=False)
    masks = (cascading_mask, alternating_mask)
    expected_mask_results = (expected_cascading_mask_result, expected_alternating_mask_result)
    for (mask, expected_mask) in zip(masks, expected_mask_results):
        columns = {'factor1': OpenPrice(mask=mask), 'mask': mask}
        pipeline = Pipeline(columns=columns)
        results = engine.run_pipeline(pipeline, dates[0], dates[(-1)])
        mask_results = results['mask'].unstack()
        check_arrays(mask_results.values, expected_mask)
        factor1_results = results['factor1'].unstack()
        factor1_expected = create_expected_results(factor1_value, mask_results)
        assert_frame_equal(factor1_results, factor1_expected)
        columns['factor2'] = RollingSumDifference(mask=mask)
        pipeline = Pipeline(columns=columns)
        results = engine.run_pipeline(pipeline, dates[0], dates[(-1)])
        mask_results = results['mask'].unstack()
        check_arrays(mask_results.values, expected_mask)
        factor1_results = results['factor1'].unstack()
        factor2_results = results['factor2'].unstack()
        factor1_expected = create_expected_results(factor1_value, mask_results)
        factor2_expected = create_expected_results(factor2_value, mask_results)
        assert_frame_equal(factor1_results, factor1_expected)
        assert_frame_equal(factor2_results, factor2_expected)
