Scaling Geometry to Match Image File



I know this is not a fiona specific question but I figure since this kind of covers a variety of modules written by the same people (or at least understood) that I might get an answer here.

I am attempting to do a mask over a population image file using geometries but they are in different projections and different scales. Here are my modules below.

I am using this set of land boundaries:
and this population image file: (with the 250 m resolution)

Here is how I read in the population file:

world_pop_image =

Here is how I do my reprojection:

Below are all my python packages

Python 3.6
Click 7
Fiona 1.8.11
Geometry 0.0.23
Pillow 6.2.1
PyContracts 1.8.12
PyGeometry 1.5.6
Rtree 0.8.3
Shapely 1.6.4.post2
affine 2.3.0
atomicwrites 1.3.0
attrs 19.3.0
certifi 2019.9.11
chardet 3.0.4
click-plugins 1.1.1
cligj 0.5.0
coverage 4.5.4
cupy 6.5.0
cycler 0.10.0
decorator 4.4.1
descartes 1.1.0
fastrlock 0.4
future 0.18.2
geopandas 0.6.1
h5py 2.10.0
idna 2.8
imageio 2.6.1
importlib-metadata 0.23
kiwisolver 1.1.0
matplotlib 3.1.1
more-itertools 7.2.0
munch 2.5.0
numpy 1.17.4
packaging 19.2
pandas 0.25.0
pip 19.3.1
pluggy 0.13.0
psutil 5.6.5
py 1.8.0
pyparsing 2.4.5
pyproj 2.4.1
pytest 5.2.1
pytest-cov 2.8.1
python-Levenshtein 0.12.0
python-dateutil 2.8.1
pytz 2019.3
rasterio 1.0.25
requests 2.22.0
scipy 1.3.1
setuptools 41.6.0
six 1.13.0
snuggs 1.4.7
urllib3 1.25.7
wcwidth 0.1.7
zipp 0.6.0


I did not finish my question. I have typed the rest.

Here is how I read in the population file:

world_pop_image =, nodata=0)

Here is how I read the boundaries file:

world_boundaries = gpd.read_file(path_to_boundaries)

Here is how I do my reprojection (the raster is in World Mollweide which is not explicitly supported so I found the below workaround):

world_boundaries.to_crs('+proj=eck4 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs')

Here is how I do my scaling:

from shapely.affinity import affine_transformation

population_image_affine = world_pop_image.transform

shapely_affine_repr = [population_image_affine.a, population_image_affine.b, population_image_affine.d, population_image_affine.e, population_image_affine.xoff, population_image_affine.yoff]

world_boundaries['geometry'] = world_boundaries['geometry].apply(lambda geometry: affine_transformation(geometry, shapely_affine_repr)


I do not know if this will be helpful at all but this is how I am doing my masks and population:

population_image_slice_arr, new_image_transform = rasterio.mask.mask(world_pop_image, [polygon_for_some_country], crop=True, nodata=0)

population_image_slice_arr[population_image_slice_arr < 0] = 0

total_population = population_image_slice_arr.sum()

I know this is incorrect because when i did manual scaling using the bounds of the image and shapely.ops.transform the population for say India would be 800 million when it should be 1.3 billion but then when I changed it to use the affine matrix the math came out to 0.0 population.


In case this helps. Here is how I did scaling it to get more accurate numbers originally before I switched but this was even flawed:

world_total_bounds = world_boundaries.total_bounds

population_image_total_bounds = world_pop_image.bounds

x_scale = (population_image_total_bounds.right - population_image_total_bounds.left) / (world_total_bounds[MAX_X] - world_total_bounds[MIN_X])
y_scale = ( - population_image_total_bounds.bottom) / (world_total_bounds[MAX_Y] - world_total_bounds[MIN_Y])

world_boundaries['geometry'] = world_boundaries['geometry'].apply(lambda geometry: shapely.ops.transform(lambda x, y, z=None: (x * x_scale, y * y_scale), geometry))



I saw the response to getting it in WGS84 and I will try that in a bit. But I think the major issue is that it actually does not include antarctic and cuts off greenland as shown in this representation (