0

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?

6
  • there's a lot of code to wade through for what most likely amounts to a relatively simple issue. usually you want to try to have the smallest amount of code to highlight the problem, and often in doing that you arrive at a solution on your own. it looks like you're passing an entire file tmax_file to the hour argument of calculate_hourly_temp. what is in that file? Commented Oct 3, 2023 at 15:58
  • We get this kind of error when an array is used in a context that expects a simple True/False value, such as an if or or. In such a case numpy (or here xarray) tries bool(arr) and raises this error. But here it's hard to trace the problem through layers of xarray and rasterio code. Commented Oct 3, 2023 at 16:24
  • @mechanical_meat tmax_file has max. temperature with different values in each cell of the array and there are several array layers (days) in the file. tmin and the other files are same, just for different variables, like daylength ("dayl"). I'm trying to cut down the code to something more minimal and will edit the question when I have revised the code. Commented Oct 3, 2023 at 17:06
  • turns out the problem was in the write statement with rasterio.open(...) I had the wrong object references in the crs attribute. I wrote crs=rascrs. It should be crs=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. Commented Oct 3, 2023 at 18:19
  • 1
    Presumably you know the rasterio docs better than I do, including what parameters its open require. This isn't a (core) python issue. rasterio appears to be a python iterface to a GDAL C library (the .pyx suggests it's cython based). rasterio apparently does not check parameters carefully at the start of the open method. The devs did not expect this kind of wrong input, and so didn't write a special test for it. Commented Oct 3, 2023 at 19:07

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.