t.rast.aggregate.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. ############################################################################
  4. #
  5. # MODULE: t.rast.aggregate
  6. # AUTHOR(S): Soeren Gebbert
  7. #
  8. # PURPOSE: Temporally aggregates the maps of a space time raster dataset by a user defined granularity.
  9. # COPYRIGHT: (C) 2011-2017 by the GRASS Development Team
  10. #
  11. # This program is free software; you can redistribute it and/or modify
  12. # it under the terms of the GNU General Public License as published by
  13. # the Free Software Foundation; either version 2 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. #
  21. #############################################################################
  22. #%module
  23. #% description: Aggregates temporally the maps of a space time raster dataset by a user defined granularity.
  24. #% keyword: temporal
  25. #% keyword: aggregation
  26. #% keyword: raster
  27. #% keyword: time
  28. #%end
  29. #%option G_OPT_STRDS_INPUT
  30. #%end
  31. #%option G_OPT_STRDS_OUTPUT
  32. #%end
  33. #%option
  34. #% key: basename
  35. #% type: string
  36. #% label: Basename of the new generated output maps
  37. #% description: Either a numerical suffix or the start time (s-flag) separated by an underscore will be attached to create a unique identifier
  38. #% required: yes
  39. #% multiple: no
  40. #% gisprompt:
  41. #%end
  42. #%option
  43. #% key: suffix
  44. #% type: string
  45. #% description: Suffix to add at basename: set 'gran' for granularity, 'time' for the full time format, 'num' for numerical suffix with a specific number of digits (default %05)
  46. #% answer: gran
  47. #% required: no
  48. #% multiple: no
  49. #%end
  50. #%option
  51. #% key: granularity
  52. #% type: string
  53. #% description: Aggregation granularity, format absolute time "x years, x months, x weeks, x days, x hours, x minutes, x seconds" or an integer value for relative time
  54. #% required: yes
  55. #% multiple: no
  56. #%end
  57. #%option
  58. #% key: method
  59. #% type: string
  60. #% description: Aggregate operation to be performed on the raster maps
  61. #% required: yes
  62. #% multiple: no
  63. #% options: average,count,median,mode,minimum,min_raster,maximum,max_raster,stddev,range,sum,variance,diversity,slope,offset,detcoeff,quart1,quart3,perc90,quantile,skewness,kurtosis
  64. #% answer: average
  65. #%end
  66. #%option
  67. #% key: offset
  68. #% type: integer
  69. #% description: Offset that is used to create the output map ids, output map id is generated as: basename_ (count + offset)
  70. #% required: no
  71. #% multiple: no
  72. #% answer: 0
  73. #%end
  74. #%option
  75. #% key: nprocs
  76. #% type: integer
  77. #% description: Number of r.series processes to run in parallel
  78. #% required: no
  79. #% multiple: no
  80. #% answer: 1
  81. #%end
  82. #%option
  83. #% key: file_limit
  84. #% type: integer
  85. #% description: The maximum number of open files allowed for each r.series process
  86. #% required: no
  87. #% multiple: no
  88. #% answer: 1000
  89. #%end
  90. #%option G_OPT_T_SAMPLE
  91. #% options: equal,overlaps,overlapped,starts,started,finishes,finished,during,contains
  92. #% answer: contains
  93. #%end
  94. #%option G_OPT_T_WHERE
  95. #%end
  96. #%flag
  97. #% key: n
  98. #% description: Register Null maps
  99. #%end
  100. import grass.script as gcore
  101. ############################################################################
  102. def main():
  103. # lazy imports
  104. import grass.temporal as tgis
  105. # Get the options
  106. input = options["input"]
  107. output = options["output"]
  108. where = options["where"]
  109. gran = options["granularity"]
  110. base = options["basename"]
  111. register_null = flags["n"]
  112. method = options["method"]
  113. sampling = options["sampling"]
  114. offset = options["offset"]
  115. nprocs = options["nprocs"]
  116. file_limit = options["file_limit"]
  117. time_suffix = options["suffix"]
  118. topo_list = sampling.split(",")
  119. tgis.init()
  120. dbif = tgis.SQLDatabaseInterfaceConnection()
  121. dbif.connect()
  122. sp = tgis.open_old_stds(input, "strds", dbif)
  123. map_list = sp.get_registered_maps_as_objects(where=where, order="start_time", dbif=dbif)
  124. if not map_list:
  125. dbif.close()
  126. gcore.fatal(_("Space time raster dataset <%s> is empty") % input)
  127. # We will create the strds later, but need to check here
  128. tgis.check_new_stds(output, "strds", dbif, gcore.overwrite())
  129. start_time = map_list[0].temporal_extent.get_start_time()
  130. if sp.is_time_absolute():
  131. start_time = tgis.adjust_datetime_to_granularity(start_time, gran)
  132. # We use the end time first
  133. end_time = map_list[-1].temporal_extent.get_end_time()
  134. has_end_time = True
  135. # In case no end time is available, then we use the start time of the last map layer
  136. if end_time is None:
  137. end_time = map_list[- 1].temporal_extent.get_start_time()
  138. has_end_time = False
  139. granularity_list = []
  140. # Build the granularity list
  141. while True:
  142. if has_end_time is True:
  143. if start_time >= end_time:
  144. break
  145. else:
  146. if start_time > end_time:
  147. break
  148. granule = tgis.RasterDataset(None)
  149. start = start_time
  150. if sp.is_time_absolute():
  151. end = tgis.increment_datetime_by_string(start_time, gran)
  152. granule.set_absolute_time(start, end)
  153. else:
  154. end = start_time + int(gran)
  155. granule.set_relative_time(start, end, sp.get_relative_time_unit())
  156. start_time = end
  157. granularity_list.append(granule)
  158. output_list = tgis.aggregate_by_topology(granularity_list=granularity_list, granularity=gran,
  159. map_list=map_list,
  160. topo_list=topo_list, basename=base, time_suffix=time_suffix,
  161. offset=offset, method=method, nprocs=nprocs, spatial=None,
  162. overwrite=gcore.overwrite(), file_limit=file_limit)
  163. if output_list:
  164. temporal_type, semantic_type, title, description = sp.get_initial_values()
  165. output_strds = tgis.open_new_stds(output, "strds", temporal_type,
  166. title, description, semantic_type,
  167. dbif, gcore.overwrite())
  168. if register_null:
  169. register_null=False
  170. else:
  171. register_null=True
  172. tgis.register_map_object_list("rast", output_list, output_strds, register_null,
  173. sp.get_relative_time_unit(), dbif)
  174. # Update the raster metadata table entries with aggregation type
  175. output_strds.set_aggregation_type(method)
  176. output_strds.metadata.update(dbif)
  177. dbif.close()
  178. if __name__ == "__main__":
  179. options, flags = gcore.parser()
  180. main()