I am using several rasters with conditional methods. I'm still learning Python, so some of this probably pretty clunky. There are no errors returned when I run the conditional function. Here is the part that runs without problem:
import rasterio
import rioxarray as rxr
import numpy as np
from math import sin, pi, exp
from multiprocess import Pool
from rasterio.crs import CRS
from rasterio.transform import Affine
import os
os.environ['PROJ_LIB'] = 'C:/OSGeo4W64/share/proj/'
# First function. Use time of day and other variables to calculate temp for an hour
def calculate_hourly_temp(hour, dayl, tmin, tmaxb, tmina, tmax):
TC = 4
P = 1.5
dayl2 = dayl[hour, :, :] / 3600
nightl = 24 - dayl2
sunrise = 12 - 0.5 * dayl2
sunset = 12 + 0.5 * dayl2
zero_rast = dayl2
zero_rast[zero_rast > 0] = 0
time_bin1 = zero_rast
time_bin1[time_bin1 >= 0] = 13.5
# masks for different parts of day
mask1 = hour < sunrise
# time_bin1 is generally around hottest part of day
mask2 = (hour >= sunrise) & (hour < time_bin1)
mask3 = (hour >= time_bin1) & (hour < sunset)
mask4 = hour >= sunset
# apply the masks with condition
temp1 = np.where(mask1, tmin[hour,:,:] - (tmin[hour,:,:] + (tmaxb[hour,:,:] - tmin[hour,:,:]) * np.sin(pi * (dayl2 / (dayl2 + 2 * P)))) * np.exp(-nightl / TC), 0)
temp2 = np.where(mask1, (tmin[hour,:,:] + (tmaxb[hour,:,:] - tmin[hour,:,:]) * np.sin(pi * (dayl2 / (dayl2 + 2 * P)))) - tmin[hour,:,:], 0)
temp3 = np.where(mask1, np.exp(-(hour + 24 - sunset) / TC), 0)
result1 = (temp1 + temp2 * temp3) / (1.0 - np.exp(-nightl / TC))
result2 = np.where(mask2, tmin[hour,:,:] + (tmax[hour,:,:] - tmin[hour,:,:]) * np.sin(pi * (hour - sunrise) / (dayl2 + 2 * P)), 0)
result3 = np.where(mask3, tmina[hour,:,:] + (tmax[hour,:,:] - tmina[hour,:,:]) * np.sin(pi * (hour - sunrise) / (dayl2 + 2 * P)), 0)
temp1 = np.where(mask4, tmin[hour,:,:] - (tmin[hour,:,:] + (tmax[hour,:,:] - tmin[hour,:,:]) * np.sin(pi * (dayl2 / (dayl2 + 2 * P)))) * np.exp(-nightl / TC), 0)
temp2 = np.where(mask4, (tmin[hour,:,:] + (tmax[hour,:,:] - tmin[hour,:,:]) * np.sin(pi * (dayl2 / (dayl2 + 2 * P)))) - tmin[hour,:,:], 0)
temp3 = np.where(mask4, np.exp(-(hour - sunset) / TC), 0)
result4 = (temp1 + temp2 * temp3) / (1 - np.exp(-nightl / TC))
return result1 + result2 + result3 + result4
def calculate_temps(tmax_file, tmin_file, vp_file, dayl_file, tmaxb_file, tmina_file):
tmax_src = rxr.open_rasterio(tmax_file)
tmin_src = rxr.open_rasterio(tmin_file)
vp_src = rxr.open_rasterio(vp_file)
dayl_src = rxr.open_rasterio(dayl_file)
tmaxb_src = rxr.open_rasterio(tmaxb_file)
tmina_src = rxr.open_rasterio(tmina_file)
tmin = tmin_src.values
tmax = tmax_src.values
vp = vp_src.values
dayl = dayl_src.values
tmaxb = tmaxb_src.values
tmina = tmina_src.values
rascrs = tmax_src.rio.crs
hourly_temps = tmax
hourly_temps[hourly_temps > 0] = 0
print(hourly_temps.shape)
for hour in range(0, 24):
np.copyto(hourly_temps[hour, :,:], calculate_hourly_temp(hour, dayl, tmin, tmaxb, tmina, tmax))
return hourly_temps
tmax_file = "Q:/Shared drives/Data/tmax9.tif"
tmin_file = "Q:/Shared drives/Data/tmin9.tif"
vp_file = "Q:/Shared drives/Data/vp9.tif"
dayl_file = "Q:/Shared drives/Data/dayl9.tif"
tmaxb_file = "Q:/Shared drives/Data/tmxb9.tif"
tmina_file = "Q:/Shared drives/Data/tmna9.tif"
rascrs = rxr.open_rasterio(tmax_file)
crsras = rascrs.rio.crs
transfras = rascrs.rio.transform()
transout = rasterio.Affine(transfras[0], transfras[1], transfras[2], transfras[3], transfras[4], transfras[5])
output_file = "Q:/My Drive/temp/output.tif"
tempraster = calculate_hourly_temps(tmax_file, tmin_file, vp_file, dayl_file, tmaxb_file, tmina_file)
num_layers = tempraster.shape[0]
# Get the height and width of the raster
height, width = tempraster.shape[1], tempraster.shape[2]
That all runs without error. When I want to write to file with
with rasterio.open(output_file, 'w', driver='GTiff', height=height, width=width, count=num_layers, dtype=tempraster.dtype, crs=rascrs, transform=transfras) as dst:
# Loop through each layer and write it to the file
for layer in range(num_layers):
dst.write(tempraster[layer], layer + 1) # Layers are 1-indexed in rasterio
I get this error:
Traceback (most recent call last): File "", line 1, in File "C:\Users\pipenvs\pythonrast.venv\lib\site-packages\rasterio\env.py", line 451, in wrapper return f(*args, **kwds)
File "C:\Users\pipenvs\pythonrast.venv\lib\site-packages\rasterio_init_.py", line 329, in open dataset = writer(
File "rasterio_io.pyx", line 1560, in rasterio._io.DatasetWriterBase.init
File "C:\Users\pipenvs\pythonrast.venv\lib\site-packages\xarray\core\common.py", line 152, in bool return bool(self.values) ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
From what I've read, it seems like the lines that create "mask1" and "mask2" and "temp1", all in the calculate_hourly_temp function (first function) would be the culprits for the error, but I only get the error when I use with rasterio_open... to write the resulting object tempraster to file. I don't know why or how to fix this. Can someone suggest a way to write the object without error or tell me if there something else going on?
tmax_fileto thehourargument ofcalculate_hourly_temp. what is in that file?iforor. In such a casenumpy(or herexarray) triesbool(arr)and raises this error. But here it's hard to trace the problem through layers ofxarrayandrasteriocode.with rasterio.open(...)I had the wrong object references in thecrsattribute. I wrotecrs=rascrs. It should becrs=crsras. That seems like an odd error message for the problem, but I don't know Python, so maybe it makes sense to people who know. I fixed that and the file writes as expected.rasteriodocs better than I do, including what parameters itsopenrequire. This isn't a (core) python issue.rasterioappears to be a python iterface to a GDAL C library (the.pyxsuggests it's cython based).rasterioapparently does not check parameters carefully at the start of theopenmethod. The devs did not expect this kind of wrong input, and so didn't write a special test for it.