Skip to main content

Comprehensive Python library for scientifically rigorous land use change analysis using the Pontius-Aldwaik intensity analysis methodology. Complete API with contingency tables, intensity analysis, and rich visualizations.

Project description

Land Use Intensity Analysis 🌍

PyPI version Python 3.8+ License: MIT

A comprehensive Python library for scientifically rigorous land use change analysis using the Pontius-Aldwaik intensity analysis methodology.

🌟 What does it do?

Transform your land cover raster data into meaningful insights about environmental change:

  1. Quantify Changes: Calculate transition matrices and area statistics from multi-temporal raster data
  2. Intensity Analysis: Apply the proven Pontius-Aldwaik methodology for interval, category, and transition-level analysis
  3. Rich Visualizations: Create publication-ready Sankey diagrams, heatmaps, spatial maps, and statistical plots
  4. Spatial Analysis: Process GeoTIFF files with built-in raster handling and spatial change detection

✨ Key Features

  • 🔬 Scientific Rigor: Implements the established Pontius-Aldwaik intensity analysis methodology
  • 📊 Rich Visualizations: Sankey diagrams, transition matrices, spatial maps, and statistical plots using matplotlib and plotly
  • 🗺️ Spatial Support: Direct processing of GeoTIFF files and numpy arrays
  • 🎯 Object-Oriented Design: Clean API with ContingencyTable, IntensityAnalyzer, and MultiStepAnalyzer classes
  • 📈 Multi-temporal Analysis: Support for analyzing changes across multiple time periods
  • 🔧 Comprehensive Toolkit: Complete suite of utility functions for data processing and validation

🚀 Installation

pip install landuse-intensity-analysis

📖 Quick Start

Basic Analysis Example

import numpy as np
import landuse_intensity as lui

# Step 1: Create contingency table from rasters
# Example with 2 time periods and 3 land use classes
raster_t1 = np.array([[1, 1, 2], [1, 2, 3], [2, 3, 3]])  # Time 1
raster_t2 = np.array([[1, 2, 2], [2, 2, 3], [3, 3, 3]])  # Time 2

# Create contingency table
ct = lui.ContingencyTable.from_rasters(
    raster_t1, raster_t2, 
    labels1=['Forest', 'Agriculture', 'Urban', 'Water'],
    labels2=['Forest', 'Agriculture', 'Urban', 'Water']
)

# Step 2: Run intensity analysis
analyzer = lui.IntensityAnalyzer(ct)
results = analyzer.full_analysis()

# Step 3: Display results
print("Contingency Table:")
print(ct.table)
print(f"\nTotal Change: {ct.total_change} pixels")
print(f"Persistence: {ct.persistence} pixels")

# Step 4: Create visualizations
from landuse_intensity import visualization as viz

# Sankey diagram
viz.plot_single_step_sankey(
    ct.table, 
    title="Land Use Transitions",
    save_path="sankey_diagram.html"
)

# Transition matrix heatmap
viz.plot_transition_matrix_heatmap(
    ct.table,
    title="Land Use Transition Matrix",
    save_path="transition_matrix.png"
)

Working with Real Raster Files

import landuse_intensity as lui

# Load raster data
raster1, metadata1 = lui.read_raster("land_cover_2000.tif")
raster2, metadata2 = lui.read_raster("land_cover_2020.tif")

# Create contingency table
contingency_df = lui.raster_to_contingency_table(
    raster1, raster2,
    class_names=['Forest', 'Agriculture', 'Urban', 'Water']
)

# Initialize analysis
ct = lui.ContingencyTable(contingency_df)
analyzer = lui.IntensityAnalyzer(ct)

# Perform complete analysis
results = analyzer.analyze()
print("Interval Level Analysis:", results['interval'])
print("Category Level Analysis:", results['category'])

Multi-Temporal Analysis

import landuse_intensity as lui

# Load multiple time periods
rasters = [
    lui.read_raster("land_cover_1990.tif")[0],
    lui.read_raster("land_cover_2000.tif")[0], 
    lui.read_raster("land_cover_2010.tif")[0],
    lui.read_raster("land_cover_2020.tif")[0]
]

time_labels = ['1990', '2000', '2010', '2020']

# Multi-step analysis
multi_analyzer = lui.MultiStepAnalyzer(rasters, time_labels)
multi_results = multi_analyzer.analyze_all_steps()

print("Multi-step Analysis Results:")
for step, result in multi_results.items():
    print(f"{step}: {result['interval']['annual_change_rate']:.2f}% annual change")

� Complete API Reference

Core Classes

ContingencyTable

Main class for handling transition matrices:

# Create from rasters
ct = lui.ContingencyTable.from_rasters(raster1, raster2, labels1, labels2)

# Create from existing data  
ct = lui.ContingencyTable(dataframe_or_array)

# Properties
ct.table              # Access transition matrix
ct.total_area        # Total number of pixels/area
ct.persistence       # Unchanged pixels
ct.total_change      # Changed pixels
ct.validate()        # Validate table structure

IntensityAnalyzer

Implements Pontius-Aldwaik intensity analysis:

analyzer = lui.IntensityAnalyzer(contingency_table)

# Analysis methods
analyzer.analyze_interval_level()    # Overall change intensity
analyzer.analyze_category_level()    # Class-specific gains/losses  
analyzer.analyze_transition_level(from_class, to_class)  # Transition intensity
analyzer.analyze()                   # Complete analysis
analyzer.full_analysis()            # Returns AnalysisResults object

MultiStepAnalyzer

For multi-temporal analysis:

analyzer = lui.MultiStepAnalyzer(raster_list, time_labels)

analyzer.analyze_all_steps()         # Step-by-step analysis
analyzer.analyze_overall_change()    # Overall change summary
analyzer.compare_step_vs_overall()   # Compare step vs overall rates

ChangeAnalyzer

For spatial change detection:

change_analyzer = lui.ChangeAnalyzer(raster1, raster2)

change_analyzer.analyze()            # Basic change detection
change_analyzer.detect_hotspots()    # Change hotspot detection
change_analyzer.create_change_map()  # Spatial change mapping

Visualization Functions

Graph Visualizations

From landuse_intensity.graph_visualization:

from landuse_intensity import graph_visualization as gv

# Sankey diagrams
gv.plot_single_step_sankey(
    contingency_table, 
    title="Land Use Transitions",
    save_path="sankey.html"
)

# Transition matrix heatmaps
gv.plot_transition_matrix_heatmap(
    contingency_table,
    title="Transition Matrix",
    save_path="heatmap.png"
)

# Bar plots for LULC analysis
gv.plot_barplot_lulc(
    lulc_data,
    title="Land Use Areas",
    save_path="barplot.png"
)

# Gain/Loss analysis
gv.plot_gain_loss_analysis(
    contingency_table,
    title="Gain/Loss Analysis"
)

# Accuracy assessment
gv.plot_accuracy_assessment(
    observed, predicted,
    save_path="accuracy.png"
)

# Confusion matrix
gv.plot_confusion_matrix(
    true_labels, predicted_labels
)

Spatial Visualizations

From landuse_intensity.map_visualization:

from landuse_intensity import map_visualization as mv

# Spatial change maps
mv.plot_spatial_change_map(
    raster_t1, raster_t2,
    title="Land Use Change Map",
    save_path="change_map.png"
)

# Multi-temporal maps
mv.plot_multi_temporal_maps(
    raster_list, time_labels,
    title="Land Use Over Time"
)

# Change detection
mv.plot_change_detection_map(
    raster_t1, raster_t2,
    title="Change Detection"
)

# Interactive maps
mv.plot_interactive_map(
    raster_data, coordinates,
    save_path="interactive_map.html"
)

# Elevation models
mv.plot_elevation_model(
    elevation_raster,
    title="Digital Elevation Model"
)

Advanced Visualizations

From landuse_intensity.visualization:

from landuse_intensity import visualization as viz

# Intensity analysis plots
viz.plot_intensity_analysis(
    intensity_results,
    title="Pontius Intensity Analysis"
)

# Multi-step Sankey
viz.plot_multi_step_sankey(
    transitions_list,
    time_labels=time_labels
)

# Spatial change with persistence
viz.plot_persistence_map(
    raster_t1, raster_t2,
    title="Persistence Analysis"
)

# Temporal land change
viz.plot_temporal_land_change(
    raster_list, time_labels,
    save_path="temporal_change.png"
)

# Change frequency mapping
viz.plot_change_frequency_map(
    raster_list,
    title="Change Frequency Analysis"
)

Utility Functions

Data Processing

import landuse_intensity as lui

# Demo data generation
raster_t1, raster_t2 = lui.demo_landscape()

# Data validation
is_valid = lui.validate_data(raster_data)

# Area calculations
area_matrix = lui.calculate_area_matrix(contingency_table, pixel_area=900)

# Change summary
summary = lui.get_change_summary(contingency_table)

# Area formatting
label = lui.format_area_label(1500.5, units="hectares")

# Transition naming
names = lui.create_transition_names(
    from_classes=['Forest', 'Agriculture'], 
    to_classes=['Urban', 'Water']
)

Image Processing

import landuse_intensity as lui

# Create contingency table from rasters
ct = lui.create_contingency_table(raster1, raster2, labels=['Forest', 'Urban'])

# Calculate change map
change_map = lui.calculate_change_map(raster_t1, raster_t2)

# Apply majority filter  
filtered = lui.apply_majority_filter(raster, window_size=3)

# Calculate patch metrics
metrics = lui.calculate_patch_metrics(raster, class_value=1)

# Resample raster
resampled = lui.resample_raster(raster, target_shape=(100, 100))

# Align rasters
aligned1, aligned2 = lui.align_rasters(raster1, raster2)

# Validate raster
is_valid = lui.validate_raster(raster)

# Mask raster
masked = lui.mask_raster(raster, mask, nodata_value=-9999)

Raster Handling

import landuse_intensity as lui

# Read raster file
raster_data, metadata = lui.read_raster("landcover.tif")

# Write raster file
lui.write_raster(
    raster_data, "output.tif", 
    metadata=metadata,
    nodata_value=-9999
)

# Convert rasters to contingency table
contingency_df = lui.raster_to_contingency_table(
    raster1, raster2,
    class_names=['Forest', 'Agriculture', 'Urban']
)

# Load demo data
demo_raster1, demo_raster2 = lui.load_demo_data()

# Raster summary statistics
summary = lui.raster_summary(raster)

# Reclassify raster
reclassified = lui.reclassify_raster(
    raster, 
    reclass_dict={1: 10, 2: 20, 3: 30}
)

📊 Analysis Functions

Main Analysis Function

# One-step comprehensive analysis
results = lui.analyze_land_use_change(
    raster1=raster_t1,
    raster2=raster_t2, 
    area_calculation=True,
    intensity_analysis=True,
    save_tables=True,
    output_dir="./results/"
)

🎯 Complete Example: Real Dataset Analysis

import landuse_intensity as lui
import numpy as np

# 1. Load real raster data
raster_2000, meta_2000 = lui.read_raster("cerrado_2000.tif")
raster_2010, meta_2010 = lui.read_raster("cerrado_2010.tif") 
raster_2020, meta_2020 = lui.read_raster("cerrado_2020.tif")

# 2. Create contingency tables
ct_2000_2010 = lui.ContingencyTable.from_rasters(
    raster_2000, raster_2010,
    labels1=['Forest', 'Savanna', 'Agriculture', 'Pasture', 'Urban'],
    labels2=['Forest', 'Savanna', 'Agriculture', 'Pasture', 'Urban']
)

ct_2010_2020 = lui.ContingencyTable.from_rasters(
    raster_2010, raster_2020,
    labels1=['Forest', 'Savanna', 'Agriculture', 'Pasture', 'Urban'],
    labels2=['Forest', 'Savanna', 'Agriculture', 'Pasture', 'Urban']
)

# 3. Intensity analysis
analyzer_2000_2010 = lui.IntensityAnalyzer(ct_2000_2010)
analyzer_2010_2020 = lui.IntensityAnalyzer(ct_2010_2020)

results_2000_2010 = analyzer_2000_2010.analyze()
results_2010_2020 = analyzer_2010_2020.analyze()

# 4. Multi-temporal analysis
multi_analyzer = lui.MultiStepAnalyzer(
    [raster_2000, raster_2010, raster_2020],
    ['2000', '2010', '2020']
)
multi_results = multi_analyzer.analyze_all_steps()

# 5. Create visualizations
from landuse_intensity import graph_visualization as gv
from landuse_intensity import map_visualization as mv

# Sankey diagrams for each period
gv.plot_single_step_sankey(
    ct_2000_2010.table,
    title="Cerrado Land Use Transitions 2000-2010",
    save_path="sankey_2000_2010.html"
)

gv.plot_single_step_sankey(
    ct_2010_2020.table, 
    title="Cerrado Land Use Transitions 2010-2020",
    save_path="sankey_2010_2020.html"
)

# Spatial change maps
mv.plot_spatial_change_map(
    raster_2000, raster_2020,
    title="Cerrado Land Use Change 2000-2020",
    save_path="cerrado_change_map.png"
)

# Multi-temporal maps
mv.plot_multi_temporal_maps(
    [raster_2000, raster_2010, raster_2020],
    ['2000', '2010', '2020'],
    title="Cerrado Land Use Evolution"
)

# 6. Export results
print("=== ANALYSIS RESULTS ===")
print(f"Period 2000-2010:")
print(f"  Annual change rate: {results_2000_2010['interval']['annual_change_rate']:.2f}%")
print(f"  Total change: {ct_2000_2010.total_change} pixels")

print(f"Period 2010-2020:")  
print(f"  Annual change rate: {results_2010_2020['interval']['annual_change_rate']:.2f}%")
print(f"  Total change: {ct_2010_2020.total_change} pixels")

# Export contingency tables
ct_2000_2010.table.to_csv("contingency_2000_2010.csv")
ct_2010_2020.table.to_csv("contingency_2010_2020.csv")

📚 References

This library implements the Pontius-Aldwaik intensity analysis methodology:

  • Aldwaik, S. Z., & Pontius Jr, R. G. (2012). Intensity analysis to unify measurements of size and stationarity of land changes by interval, category, and transition. Landscape and Urban Planning, 106(1), 103-114.

  • Pontius Jr, R. G., & Millones, M. (2011). Death to Kappa: birth of quantity disagreement and allocation disagreement for accuracy assessment. International Journal of Remote Sensing, 32(15), 4407-4429.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

📮 Support

If you encounter any issues or have questions:

  1. Check the examples in the examples/ directory
  2. Read the documentation
  3. Open an issue on GitHub

🎯 Version Information

  • Current Version: 2.0.3
  • Python Requirements: Python 3.8+
  • Key Dependencies: numpy, pandas, matplotlib, plotly, rasterio

Made with ❤️ for the geospatial and environmental science community

  • Smart Detection: No need to manually specify analysis type
  • Methodology Compatible: Follows established methodology
  • Flexible: Override auto-detection when needed
  • Unified Interface: Single function for all analysis types

Raster Stacking and Year Detection

Raster Stacking Options

1. Automatic Directory Loading:

from landuse_intensity.raster import load_rasters

# Load all .tif files from directory
rasters = load_rasters("data/landuse/")
# Automatically finds and stacks: landuse_1990.tif, landuse_2000.tif, landuse_2010.tif

2. Manual File Selection:

# Load specific files in custom order
files = ["landuse_1990.tif", "landuse_2005.tif", "landuse_2010.tif"]
rasters = load_rasters(files)

Scientific Background

This library implements the Pontius-Aldwaik intensity analysis methodology, which provides a comprehensive framework for understanding land use change patterns. The methodology distinguishes between:

  • Quantity of change: How much land changed category
  • Exchange: Land that would have changed even if proportions remained constant
  • Shift: Land that changed due to systematic transitions

API Reference

Core Classes

ContingencyTable

Main class for creating and managing transition matrices.

Methods:

  • from_rasters(): Create contingency table from raster data
  • validate(): Validate table data integrity
  • get_summary_stats(): Get statistical summary
  • get_transition_matrix(): Get transition matrix representation

IntensityAnalyzer

Class for performing Pontius-Aldwaik intensity analysis.

Methods:

  • analyze(): Perform intensity analysis on contingency table
  • full_analysis(): Complete analysis with all metrics
  • get_category_analysis(): Category-level intensity analysis
  • get_transition_analysis(): Transition-level intensity analysis

Data Format

The library expects land use data in numpy arrays or pandas DataFrames:

# Raster data (numpy arrays)
raster_1990 = np.array([[1, 1, 2], [1, 2, 3], [2, 3, 3]])
raster_2000 = np.array([[1, 2, 2], [2, 2, 3], [3, 3, 3]])

# Or pandas DataFrame
contingency_df = pd.DataFrame({
    'Forest->Forest': [100, 0, 0],
    'Forest->Agriculture': [20, 0, 0],
    'Agriculture->Agriculture': [0, 80, 0]
})

Visualization Gallery

The library provides several types of visualizations:

  • Intensity Maps: Spatial distribution of land use intensity
  • Transition Matrices: Category transition probabilities
  • Time Series Plots: Temporal evolution of land use patterns
  • Chord Diagrams: Flow visualization between categories
  • Sankey Diagrams: Flow-based transition visualization

Advanced Usage

Working with Large Datasets

# For large raster datasets, consider memory usage
import numpy as np
from landuse_intensity import ContingencyTable

# Process in chunks for very large rasters
def process_large_raster(raster1, raster2, chunk_size=1000):
    height, width = raster1.shape
    results = []
    
    for i in range(0, height, chunk_size):
        for j in range(0, width, chunk_size):
            chunk1 = raster1[i:i+chunk_size, j:j+chunk_size]
            chunk2 = raster2[i:i+chunk_size, j:j+chunk_size]
            
            ct = ContingencyTable.from_rasters(chunk1, chunk2)
            results.append(ct)
    
    return results

Custom Analysis Parameters

# Customize analysis with specific parameters
from landuse_intensity import IntensityAnalyzer

# Create analyzer with custom settings
analyzer = IntensityAnalyzer()

# Perform analysis with specific options
results = analyzer.analyze(
    contingency_table=ct,
    include_interval=True,
    include_category=True,
    include_transition=True
)

Spatial Analysis

# Load geospatial data
import rasterio
import xarray as xr

with rasterio.open('land_use_1990.tif') as src:
    data_1990 = src.read(1)

with rasterio.open('land_use_2000.tif') as src:
    data_2000 = src.read(1)

# Perform spatial intensity analysis
spatial_results = analyzer.spatial_intensity_analysis(
    data_1990, data_2000,
    transform=src.transform
)

📚 Complete Documentation

Usage

🔧 Key Features

  • Raster Loading: Multiple methods (automatic, manual, dataset)
  • Year Detection: Automatic year extraction from filenames
  • Contingency Tables: Transition matrix generation
  • Intensity Analysis: Pontius-Aldwaik methodology
  • Visualizations: Modern interactive plots
  • Change Maps: Spatial analysis and mapping
  • Export Options: CSV, JSON, HTML formats

📋 Complete Analysis Workflow

# 1. Load raster data
from landuse_intensity import read_raster
raster1, meta1 = read_raster("landuse_1990.tif")
raster2, meta2 = read_raster("landuse_2000.tif")

# 2. Generate contingency table
from landuse_intensity import ContingencyTable
ct = ContingencyTable.from_rasters(raster1, raster2)

# 3. Perform intensity analysis
from landuse_intensity import IntensityAnalyzer
analyzer = IntensityAnalyzer(ct)
results = analyzer.full_analysis()

# 4. Create visualizations
from landuse_intensity import visualization as viz
viz.plot_single_step_sankey(ct.table, title="Land Use Transitions")
viz.plot_transition_matrix_heatmap(ct.table, title="Transition Matrix")

# 5. Generate change maps
from landuse_intensity import image_processing
change_map = image_processing.calculate_change_map(raster1, raster2)

# 6. Export results
ct.table.to_csv("contingency_table.csv")

Examples

The library includes comprehensive examples demonstrating various land use analysis capabilities:

# Basic intensity analysis example
import numpy as np
import landuse_intensity as lui

# Generate demo data
raster_t1, raster_t2 = lui.demo_landscape()

# Create contingency table
ct = lui.ContingencyTable.from_rasters(raster_t1, raster_t2)

# Perform intensity analysis
analyzer = lui.IntensityAnalyzer(ct)
results = analyzer.full_analysis()

# Create visualizations
import landuse_intensity.visualization as viz
viz.plot_single_step_sankey(ct.table, title="Land Use Transitions")
viz.plot_transition_matrix_heatmap(ct.table, title="Transition Matrix")

print(f"Analysis completed! Total change: {ct.total_change} pixels")

Contributing

We welcome contributions! Please see our GitHub repository for details on contributing to the project.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Citation

If you use this library in your research, please cite:

@software{landuse_intensity_analysis,
  title = {Land Use Intensity Analysis},
  author = {LandUse Intensity Analysis Contributors},
  url = {https://github.com/your-repo/landuse-intensity-analysis},
  version = {1.0.3a1},
  date = {2024}
}

Support

Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

landuse_intensity_analysis-1.0.0a1.tar.gz (64.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

landuse_intensity_analysis-1.0.0a1-py3-none-any.whl (61.8 kB view details)

Uploaded Python 3

File details

Details for the file landuse_intensity_analysis-1.0.0a1.tar.gz.

File metadata

File hashes

Hashes for landuse_intensity_analysis-1.0.0a1.tar.gz
Algorithm Hash digest
SHA256 dc049625f27f59852bdddf4bdde6a05c81b64ad5144f8d2d59b3d0b2fdaa9a1c
MD5 da08c4cb3478739994cb8b69de37fed1
BLAKE2b-256 77f5df40fe7d03d48329ef99c25e37f1930d994e235477584e4530b7fc1e11db

See more details on using hashes here.

File details

Details for the file landuse_intensity_analysis-1.0.0a1-py3-none-any.whl.

File metadata

File hashes

Hashes for landuse_intensity_analysis-1.0.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 2374335c1feac4d6903d4ed8061017df29966271b1638a0fbab144a49a991a77
MD5 89efe213698d2c8bfe021ebc38a560dc
BLAKE2b-256 258cea053dd338d84c9a2bdbd550774d04f55d5b62d03ae371a3c73031f7b791

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page