def test_model_run_2(self):
        """Coastal Blue Carbon: Test CBC without analysis year."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        self.args['analysis_year'] = None
        self.args['lulc_baseline_year'] = 2000
        self.args['lulc_transition_maps_list'] = [
            self.args['lulc_transition_maps_list'][0]
        ]
        self.args['lulc_transition_years_list'] = [2005]

        cbc.execute(self.args)
        netseq_output_raster = os.path.join(
            self.args['workspace_dir'],
            'outputs_core/total_net_carbon_sequestration_test.tif')
        netseq_array = _read_array(netseq_output_raster)

        # (Explanation for why netseq is 10.5.)
        # LULC Code: Baseline: 1 --> Year 2000: 1, Year 2005: 2
        # Initial Stock from Baseline: 5+5=10
        # Sequest:
        #    2000-->2005: (1+1.1)*5=10.5
        netseq_test = numpy.array([[cbc.NODATA_FLOAT, 10.5], [10.5, 10.5]])

        # just a simple regression test.  this demonstrates that a NaN value
        # will properly propagate across the model. the npv raster was chosen
        # because the values are determined by multiple inputs, and any changes
        # in those inputs would propagate to this raster.
        numpy.testing.assert_allclose(netseq_array,
                                      netseq_test,
                                      rtol=0,
                                      atol=1e-4)
Beispiel #2
0
    def test_model_no_valuation(self):
        """Coastal Blue Carbon: Test main model without valuation."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        self.args = _get_args(valuation=False, workspace=self.workspace_dir)
        self.args['lulc_baseline_year'] = 2000
        self.args['lulc_transition_years_list'] = [2005, 2010]
        self.args['analysis_year'] = None

        cbc.execute(self.args)
        netseq_output_raster = os.path.join(
            self.args['workspace_dir'],
            'outputs_core/total_net_carbon_sequestration_test.tif')
        netseq_array = _read_array(netseq_output_raster)

        # (Explanation for why netseq is 31.)
        # LULC Code: Baseline: 1 --> Year 2000: 1, Year 2005: 2,  Year 2010: 2
        # Initial Stock from Baseline: 5+5=10
        # Sequest:
        #    2000-->2005: (1+1.1)*5=10.5, 2005-->2010: (2+2.1)*5=20.5
        #       Total: 10.5 + 20.5 = 31.
        netseq_test = numpy.array([[cbc.NODATA_FLOAT, 31.], [31., 31.]])

        # just a simple regression test.  this demonstrates that a NaN value
        # will properly propagate across the model. the npv raster was chosen
        # because the values are determined by multiple inputs, and any changes
        # in those inputs would propagate to this raster.
        numpy.testing.assert_array_almost_equal(
            netseq_array, netseq_test, decimal=4)
Beispiel #3
0
    def test_no_transitions_with_analysis_year(self):
        """Coastal Blue Carbon: Model can run w/o trans., w/analysis yr."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        args = CBCRefactorTest.create_args(
            workspace=self.workspace_dir, transition_tuples=None,
            analysis_year=2010)

        cbc.execute(args)
Beispiel #4
0
    def test_no_transitions(self):
        """Coastal Blue Carbon: Verify model can run without transitions."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        args = CBCRefactorTest.create_args(
            workspace=self.workspace_dir, transition_tuples=None,
            analysis_year=None)

        cbc.execute(args)
Beispiel #5
0
    def test_model_one_transition_no_analysis_year(self):
        """CBC: Test the model on one transition with no analysis year.

        This test came up while looking into an issue reported on the forums:
        https://community.naturalcapitalproject.org/t/coastal-blue-carbon-negative-carbon-stocks/780/12
        """
        args = TestCBC2._create_model_args(self.workspace_dir)
        args['workspace_dir'] = os.path.join(self.workspace_dir, 'workspace')

        prior_snapshots = coastal_blue_carbon._extract_snapshots_from_table(
            args['landcover_snapshot_csv'])
        baseline_year = min(prior_snapshots.keys())
        baseline_raster = prior_snapshots[baseline_year]
        with open(args['landcover_snapshot_csv'], 'w') as snapshot_csv:
            snapshot_csv.write('snapshot_year,raster_path\n')
            snapshot_csv.write(f'{baseline_year},{baseline_raster}\n')
            snapshot_csv.write(f'2010,{prior_snapshots[2010]}\n')
        del args['analysis_year']

        # Use valuation parameters rather than price table.
        args['use_price_table'] = False
        args['inflation_rate'] = 4
        args['price'] = 1.0

        coastal_blue_carbon.execute(args)

        # Check sequestration raster
        expected_sequestration_2000_to_2010 = numpy.array([[83.5, 0.]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2000-and-2010.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2000_to_2010)
        finally:
            raster = None

        # Check valuation raster
        # Discount rate here matches the inflation rate, so the value of the 10
        # years' accumulation is just 1*(10 years of accumulation).
        expected_net_present_value_at_2010 = numpy.array([[835.0, 0.]],
                                                         dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   'net-present-value-at-2010.tif')
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_net_present_value_at_2010,
                                          rtol=1e-6)
        finally:
            raster = None
Beispiel #6
0
    def test_model_no_transitions(self):
        """CBC: Test model without transitions.

        When the model executes without transitions, we still evaluate carbon
        sequestration (accumulation only) for the whole baseline period.
        """
        args = TestCBC2._create_model_args(self.workspace_dir)
        args['workspace_dir'] = os.path.join(self.workspace_dir, 'workspace')

        prior_snapshots = coastal_blue_carbon._extract_snapshots_from_table(
            args['landcover_snapshot_csv'])
        baseline_year = min(prior_snapshots.keys())
        baseline_raster = prior_snapshots[baseline_year]
        with open(args['landcover_snapshot_csv'], 'w') as snapshot_csv:
            snapshot_csv.write('snapshot_year,raster_path\n')
            snapshot_csv.write(f'{baseline_year},{baseline_raster}\n')
        args['analysis_year'] = baseline_year + 10

        # Use valuation parameters rather than price table.
        args['use_price_table'] = False
        args['inflation_rate'] = 4
        args['price'] = 1.0

        coastal_blue_carbon.execute(args)

        # Check sequestration raster
        expected_sequestration_2000_to_2010 = numpy.array([[83.5, 0.]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2000-and-2010.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2000_to_2010)
        finally:
            raster = None

        # Check valuation raster
        # Discount rate here matches the inflation rate, so the value of the 10
        # years' accumulation is just 1*(10 years of accumulation).
        expected_net_present_value_at_2010 = numpy.array([[835.0, 0.]],
                                                         dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   'net-present-value-at-2010.tif')
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_net_present_value_at_2010,
                                          rtol=1e-6)
        finally:
            raster = None
    def test_one_transition(self):
        """Coastal Blue Carbon: Verify model can run with 1 transition."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        transition_tuples = [
            (numpy.ones((10, 10)), 2010),
        ]

        args = CBCRefactorTest.create_args(workspace=self.workspace_dir,
                                           transition_tuples=transition_tuples,
                                           analysis_year=None)

        cbc.execute(args)
Beispiel #8
0
    def test_duplicate_lulc_classes(self):
        """CBC: Raise an execption if duplicate lulc-classes."""
        args = TestCBC2._create_model_args(self.workspace_dir)
        args['workspace_dir'] = os.path.join(self.workspace_dir, 'workspace')
        with open(args['biophysical_table_path'], 'r') as table:
            lines = table.readlines()

        with open(args['biophysical_table_path'], 'a') as table:
            last_line_contents = lines[-1].strip().split(',')
            last_line_contents[0] = '3'  # assign a new code
            table.write(','.join(last_line_contents))

        with self.assertRaises(ValueError) as context:
            coastal_blue_carbon.execute(args)

        self.assertIn("`lulc-class` column must be unique",
                      str(context.exception))
Beispiel #9
0
    def test_1_transition_passes(self):
        """Coastal Blue Carbon: Test model runs with only 1 transition.

        This is a regression test addressing issue #3572
        (see: https://bitbucket.org/natcap/invest/issues/3572)
        """
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        self.args['lulc_transition_maps_list'] = \
            [self.args['lulc_transition_maps_list'][0]]
        self.args['lulc_transition_years_list'] = \
            [self.args['lulc_transition_years_list'][0]]
        self.args['analysis_year'] = None
        try:
            cbc.execute(self.args)
        except AttributeError as error:
            LOGGER.exception("Here's the traceback encountered: %s" % error)
            self.fail('CBC should not crash when only 1 transition provided')
    def test_model_run(self):
        """Coastal Blue Carbon: Test run function in main model."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        self.args['suffix'] = 'xyz'
        self.args['lulc_baseline_year'] = 2000
        self.args['lulc_transition_years_list'] = [2005, 2010]
        self.args['analysis_year'] = None

        cbc.execute(self.args)
        netseq_output_raster = os.path.join(
            self.args['workspace_dir'],
            'outputs_core/total_net_carbon_sequestration_test.tif')
        npv_output_raster = os.path.join(
            self.args['workspace_dir'],
            'outputs_core/net_present_value_at_2010_test.tif')
        netseq_array = _read_array(netseq_output_raster)
        npv_array = _read_array(npv_output_raster)

        # (Explanation for why netseq is 31.)
        # LULC Code: Baseline: 1 --> Year 2000: 1, Year 2005: 2,  Year 2010: 2
        # Initial Stock from Baseline: 5+5=10
        # Sequest:
        #    2000-->2005: (1+1.1)*5=10.5, 2005-->2010: (2+2.1)*5=20.5
        #       Total: 10.5 + 20.5 = 31.
        netseq_test = numpy.array([[cbc.NODATA_FLOAT, 31.], [31., 31.]])
        npv_test = numpy.array([[cbc.NODATA_FLOAT, 60.27801514],
                                [60.27801514, 60.27801514]])

        # just a simple regression test.  this demonstrates that a NaN value
        # will properly propagate across the model. the npv raster was chosen
        # because the values are determined by multiple inputs, and any changes
        # in those inputs would propagate to this raster.
        numpy.testing.assert_allclose(netseq_array,
                                      netseq_test,
                                      rtol=0,
                                      atol=1e-4)
        numpy.testing.assert_allclose(npv_array, npv_test, rtol=0, atol=1e-4)
Beispiel #11
0
    def test_binary(self):
        """Coastal Blue Carbon: Test CBC model against InVEST-Data."""
        from natcap.invest.coastal_blue_carbon \
            import coastal_blue_carbon as cbc

        args = {
            'workspace_dir': self.args['workspace_dir'],
            'carbon_pool_initial_uri': os.path.join(
                REGRESSION_DATA,
                'outputs_preprocessor/carbon_pool_initial_sample.csv'),
            'carbon_pool_transient_uri': os.path.join(
                REGRESSION_DATA,
                'outputs_preprocessor/carbon_pool_transient_sample.csv'),
            'discount_rate': 6.0,
            'do_economic_analysis': True,
            'do_price_table': True,
            'inflation_rate': 3.0,
            'lulc_lookup_uri': os.path.join(
                REGRESSION_DATA, 'inputs', 'lulc_lookup.csv'),
            'lulc_baseline_map_uri': os.path.join(
                REGRESSION_DATA, 'inputs/GBJC_2010_mean_Resample.tif'),
            'lulc_baseline_year': 2010,
            'lulc_transition_maps_list': [
                os.path.join(
                    REGRESSION_DATA, 'inputs/GBJC_2030_mean_Resample.tif'),
                os.path.join(
                    REGRESSION_DATA, 'inputs/GBJC_2050_mean_Resample.tif')],
            'lulc_transition_years_list': [2030, 2050],
            'price_table_uri': os.path.join(
                REGRESSION_DATA, 'inputs/Price_table_SCC3.csv'),
            'lulc_transition_matrix_uri': os.path.join(
                REGRESSION_DATA, 'outputs_preprocessor/transitions_sample.csv'),
            'price': 10.0,
            'results_suffix': '150225'
        }
        cbc.execute(args)
        npv_raster = os.path.join(
            os.path.join(
                args['workspace_dir'],
                'outputs_core/net_present_value_at_2050_150225.tif'))
        npv_array = _read_array(npv_raster)

        # this is just a regression test, but it will capture all values
        # in the net present value raster.  the npv raster was chosen because
        # the values are determined by multiple inputs, and any changes in
        # those inputs would propagate to this raster.
        u = numpy.unique(npv_array)
        u.sort()
        a = numpy.array([-76992.05, -40101.57, -34930., -34821.32,
                         0., 108.68, 6975.94, 7201.22, 7384.99],
                        dtype=numpy.float32)

        a.sort()
        numpy.testing.assert_array_almost_equal(u, a, decimal=2)

        # walk through all files in the workspace and assert that outputs have
        # the file suffix.
        non_suffixed_files = []
        for root_dir, dirnames, filenames in os.walk(self.args['workspace_dir']):
            for filename in filenames:
                if not filename.lower().endswith('.txt'):  # ignore logfile
                    basename, extension = os.path.splitext(filename)
                    if not basename.endswith('_150225'):
                        path_rel_to_workspace = os.path.relpath(
                            os.path.join(root_dir, filename),
                            self.args['workspace_dir'])
                        non_suffixed_files.append(path_rel_to_workspace)

        if non_suffixed_files:
            self.fail('%s files are missing suffixes: %s' %
                      (len(non_suffixed_files),
                       pprint.pformat(non_suffixed_files)))
Beispiel #12
0
    def test_model(self):
        """CBC: Test the model's execution."""
        args = TestCBC2._create_model_args(self.workspace_dir)
        args['workspace_dir'] = os.path.join(self.workspace_dir, 'workspace')

        coastal_blue_carbon.execute(args)

        # Sample values calculated by hand.  Pixel 0 only accumulates.  Pixel 1
        # has no accumulation (per the biophysical table) and also has no
        # emissions.
        expected_sequestration_2000_to_2010 = numpy.array([[83.5, 0]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2000-and-2010.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2000_to_2010)
        finally:
            raster = None

        expected_sequestration_2010_to_2020 = numpy.array([[-176.9792, 73.5]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2010-and-2020.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2010_to_2020,
                                          rtol=1e-6)
        finally:
            raster = None

        expected_sequestration_2020_to_2030 = numpy.array([[73.5, -28.698004]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2020-and-2030.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2020_to_2030,
                                          rtol=1e-6)
        finally:
            raster = None

        # Total sequestration is the sum of all the previous sequestration.
        expected_total_sequestration = (expected_sequestration_2000_to_2010 +
                                        expected_sequestration_2010_to_2020 +
                                        expected_sequestration_2020_to_2030)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   'total-net-carbon-sequestration.tif')
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_total_sequestration,
                                          rtol=1e-6)
        finally:
            raster = None

        expected_net_present_value_at_2030 = numpy.array(
            [[-373.67245, 837.93445]], dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   'net-present-value-at-2030.tif')
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_net_present_value_at_2030,
                                          rtol=1e-6)
        finally:
            raster = None

        # For emissions, make sure that each of the emissions sum rasters in
        # the output folder match the sum of all annual emissions from the time
        # period.
        for emissions_raster_path in glob.glob(
                os.path.join(args['workspace_dir'], 'output',
                             'carbon-emissions-between-*.tif')):
            try:
                raster = gdal.OpenEx(emissions_raster_path)
                band = raster.GetRasterBand(1)
                emissions_in_period = band.ReadAsArray()
            finally:
                band = None
                raster = None

            basename = os.path.splitext(
                os.path.basename(emissions_raster_path))[0]
            parts = basename.split('-')
            start_year = int(parts[3])
            end_year = int(parts[5])

            summed_emissions_over_time_period = numpy.array(
                [[0.0, 0.0]], dtype=numpy.float32)
            for year in range(start_year, end_year):
                for pool in ('soil', 'biomass'):
                    yearly_emissions_raster = os.path.join(
                        args['workspace_dir'], 'intermediate',
                        f'emissions-{pool}-{year}.tif')
                    try:
                        raster = gdal.OpenEx(yearly_emissions_raster)
                        band = raster.GetRasterBand(1)
                        summed_emissions_over_time_period += band.ReadAsArray()
                    finally:
                        band = None
                        raster = None
            numpy.testing.assert_allclose(emissions_in_period,
                                          summed_emissions_over_time_period)
Beispiel #13
0
    def test_model_no_analysis_year_no_price_table(self):
        """CBC: Test the model's execution."""
        args = TestCBC2._create_model_args(self.workspace_dir)
        args['workspace_dir'] = os.path.join(self.workspace_dir, 'workspace')
        del args['analysis_year']  # final year is 2020.
        args['use_price_table'] = False
        args['inflation_rate'] = 5
        args['price'] = 10.0

        coastal_blue_carbon.execute(args)

        # Sample values calculated by hand.  Pixel 0 only accumulates.  Pixel 1
        # has no accumulation (per the biophysical table) and also has no
        # emissions.
        expected_sequestration_2000_to_2010 = numpy.array([[83.5, 0]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2000-and-2010.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2000_to_2010)
        finally:
            raster = None

        expected_sequestration_2010_to_2020 = numpy.array([[-176.9792, 73.5]],
                                                          dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   ('total-net-carbon-sequestration-between-'
                                    '2010-and-2020.tif'))
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_sequestration_2010_to_2020,
                                          rtol=1e-6)
        finally:
            raster = None

        # Total sequestration is the sum of all the previous sequestration.
        expected_total_sequestration = (expected_sequestration_2000_to_2010 +
                                        expected_sequestration_2010_to_2020)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   'total-net-carbon-sequestration.tif')
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_total_sequestration,
                                          rtol=1e-6)
        finally:
            raster = None

        expected_net_present_value_at_2020 = numpy.array(
            [[-20506.314, 16123.521]], dtype=numpy.float32)
        raster_path = os.path.join(args['workspace_dir'], 'output',
                                   'net-present-value-at-2020.tif')
        try:
            raster = gdal.OpenEx(raster_path)
            numpy.testing.assert_allclose(raster.ReadAsArray(),
                                          expected_net_present_value_at_2020,
                                          rtol=1e-6)
        finally:
            raster = None