.. _icclim_ocgis: ############################################## icclim called from OpenClimateGIS - Examples ############################################## icclim indices (`ECA&D climate indices `_) are implemented in the `OpenClimateGIS `_ (Version 1.1.0) Python package. .. code:: python import ocgis rd = ocgis.RequestDataset("tas_19800101_19891231.nc", variable="tas") It is also possible to pass a list of datasets: .. code:: python rd = ocgis.RequestDataset( ["tas_19800101_19891231.nc", "tas_19900101_19991231.nc"], variable="tas" ) ******************************************************* Subsetting with ``time_range`` and/or ``time_region`` ******************************************************* .. note:: See `ocgis time_range `_ doc and `ocgis time_region `_ doc. For temporal subsetting we use the ``time_range`` parameter: .. code:: python import datetime dt1 = datetime.datetime(1985, 1, 1) dt2 = datetime.datetime(1995, 12, 31) rd = ocgis.RequestDataset( ["tas_19800101_19891231.nc", "tas_19900101_19991231.nc"], variable="tas", time_range=[dt1, dt2], ) or/and the ``time_region`` parameter: .. code:: python rd = ocgis.RequestDataset( ["tas_19800101_19891231.nc", "tas_19900101_19991231.nc"], variable="tas", time_region={"month": [6, 7, 8]}, ) .. code:: python rd = ocgis.RequestDataset( ["tas_19800101_19891231.nc", "tas_19900101_19991231.nc"], variable="tas", time_region={"year": [1989, 1990, 1991], "month": [6, 7, 8]}, ) ********************************************* Temporal aggregation with ``calc_grouping`` ********************************************* .. note:: See `ocgis calc_grouping `_ doc. Annual values: .. code:: python calc_grouping = ["year"] Monthly values: .. code:: python calc_grouping = ["year", "month"] # or calc_grouping = ['month', 'year'] Seasonal values: .. code:: python spring = [[3, 4, 5], "unique"] # spring season (MAM) summer = [[6, 7, 8], "unique"] # summer season (JJA) autumn = [[9, 10, 11], "unique"] # autumn season (SON) winter = [[12, 1, 2], "unique"] # winter season (DJF) long_winter = [[10, 11, 12, 1, 2, 3], "unique"] # winter half-year (ONDJFM) long_summer = [[4, 5, 6, 7, 8, 9], "unique"] # summer half-year (AMJJAS) ************************************** Example 1: simple indice calculation ************************************** The example below will create a netCDF file "indiceTG_1985_1995.nc" containing TG indice: .. code:: python calc_icclim = [{"func": "icclim_TG", "name": "TG"}] ops = ocgis.OcgOperations( dataset=rd, calc=calc_icclim, calc_grouping=calc_grouping, prefix="indiceTG_1985_1995", output_format="nc", add_auxiliary_files=False, ) ops.execute() ********************************************* Example 2: multivariable indice calculation ********************************************* To calculate an indice based on 2 variables: .. code:: python rd_tasmin = ocgis.RequestDataset(tasmin_19800101_19891231.nc, "tasmin") rd_tasmax = ocgis.RequestDataset(tasmax_19800101_19891231.nc, "tasmax") rds = [rd_tasmin, rd_tasmax] calc_grouping = ["year", "month"] calc_icclim = [ { "func": "icclim_ETR", "name": "ETR", "kwds": {"tasmin": "tasmin", "tasmax": "tasmax"}, } ] ops = ocgis.OcgOperations( dataset=rds, calc=calc_icclim, calc_grouping=calc_grouping, prefix="indiceETR_1980_1989", output_format="nc", add_auxiliary_files=False, ) ops.execute() .. _percentil_label: ************************************* Example 3: percentile-based indices ************************************* Calculation of percentile-based indices is more complicated. The example below shows how to calculate the TG10p indice. .. code:: python dt1 = datetime.datetime(1980, 1, 1) dt2 = datetime.datetime(1989, 12, 31) time_range_indice = [dt1, dt2] # we will calculate the indice for 10 years rd = ocgis.RequestDataset(tas_files, "tas", time_range=time_range_indice) basis_indice = rd.get() # OCGIS data object We do the same for reference period (usually the reference period is the 1961-1990 (30 years)): .. code:: python dt1_ref = datetime.datetime(1961, 1, 1) dt2_ref = datetime.datetime(1990, 12, 31) time_range_ref = [dt1_ref, dt2_ref] rd_ref = ocgis.RequestDataset(tas_files, "tas", time_range=time_range_ref) basis_ref = rd_ref.get() # OCGIS data object To get the 10th daily percentile basis of the reference period: .. code:: python values_ref = basis_ref.variables["tas"].value temporal = basis_ref.temporal.value_datetime percentile = 10 width = 5 # 5-day window from ocgis.calc.library.index.dynamic_kernel_percentile import ( DynamicDailyKernelPercentileThreshold, ) daily_percentile = DynamicDailyKernelPercentileThreshold.get_daily_percentile( values_ref, temporal, percentile, width ) # daily_percentile.shape = 366 Finally, to calculate the TG10p indice: .. code:: python calc_grouping = ["year", "month"] # or other kwds = { "percentile": percentile, "width": width, "operation": "lt", "daily_percentile": daily_percentile, } # operation: lt = "less then", beacause we count the number of days < 10th percentile calc = [{"func": "dynamic_kernel_percentile_threshold", "name": "TG10p", "kwds": kwds}] ops = ocgis.OcgOperations( dataset=rd, calc_grouping=calc_grouping, calc=calc, output_format="nc", prefix="indiceTG10p_1980_1989", add_auxiliary_files=False, ) ops.execute() ***************************************** Example 4: OPeNDAP dataset, big request ***************************************** If you want to process OPeNDAP datasets of total size more than for example the OPenDAP/THREDDS limit (500 Mbytes), use the `compute function `_ which processes data chunk-by-chunk: .. code:: python from ocgis.util.large_array import compute This function takes the *tile_dimention* parameter, so first we need to find an optimal tile dimention (number of pixels) to get a chunk less than the the OPenDAP/THREDDS limit: .. code:: python limit_opendap_mb = ( 475.0 # we reduce the limit on about 25 Mbytes (don't ask me why :) ) ) size = ops.get_base_request_size() nb_time_coordinates_rd = size["variables"]["tas"]["temporal"]["shape"][0] element_in_kb = size["total"] / reduce( lambda x, y: x * y, size["variables"]["tas"]["value"]["shape"] ) element_in_mb = element_in_kb * 0.001 import numpy as np tile_dim = np.sqrt( limit_opendap_mb / (element_in_mb * nb_time_coordinates_rd) ) # maximum chunk size .. note:: Chunks are cut along the time axis, i.e. a maximum chunk size in pixels is **tile_dimention** x **tile_dimention** x **number_time_steps**. .. figure:: /_static/chunks.png Now we can use the compute function: .. code:: python rd = ocgis.RequestDataset(input_files, variable="tas", time_range=[dt1, dt2]) ops = ocgis.OcgOperations( dataset=rd, calc=calc_icclim, calc_grouping=calc_grouping, prefix="indiceETR_1980_1989", add_auxiliary_files=False, ) compute(ops, tile_dimension=tile_dim)