Coverage for src/efts_io/attributes.py: 33.33%

7 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-07-24 10:14 +1000

1"""Management of netCDF attributes.""" 

2 

3#' Create variable attribute definition 

4#' 

5#' Create variable attribute definition 

6#' 

7#' @param type A data type identifier, as a coded description. 

8#' @param type_description description of this data type identifier. 

9#' @param location_type a character, type of location, e.g. 'Point' 

10#' @param dat_type a character, the type of data stored in this variable 

11#' @param dat_type_description a character, human readable description of the data stored in this variable 

12#' @export 

13#' @return a list of attributes, describing the type of variable stored 

14#' @examples 

15#' va = create_var_attribute_definition(type=2L, 

16#' type_description='accumulated over the preceding interval', location_type='Point') 

17#' vdef = create_variable_definition(name='rain_sim', 

18#' longname='Rainfall ensemble forecast derived from some prediction', 

19#' units='mm', missval=-9999.0, precision='double', 

20#' var_attribute=va) 

21#' 

22from efts_io.conventions import ( 

23 CATCHMENT_ATTR_KEY, 

24 COMMENT_ATTR_KEY, 

25 DAT_TYPE_ATTR_KEY, 

26 DAT_TYPE_DESCRIPTION_ATTR_KEY, 

27 INSTITUTION_ATTR_KEY, 

28 LOCATION_TYPE_ATTR_KEY, 

29 SOURCE_ATTR_KEY, 

30 TITLE_ATTR_KEY, 

31 TYPE_ATTR_KEY, 

32 TYPE_DESCRIPTION_ATTR_KEY, 

33) 

34 

35 

36def create_var_attribute_definition( 

37 data_type_code: int = 2, 

38 type_description: str = "accumulated over the preceding interval", 

39 dat_type: str = "der", 

40 dat_type_description: str = "AWAP data interpolated from observations", 

41 location_type: str = "Point", 

42) -> dict[str, str]: 

43 """Create variable attribute definition.""" 

44 return { 

45 TYPE_ATTR_KEY: str(data_type_code), 

46 TYPE_DESCRIPTION_ATTR_KEY: type_description, 

47 DAT_TYPE_ATTR_KEY: dat_type, 

48 DAT_TYPE_DESCRIPTION_ATTR_KEY: dat_type_description, 

49 LOCATION_TYPE_ATTR_KEY: location_type, 

50 } 

51 

52 

53# # The following cannot be hard-coded. ncdf4::ncatt_put(nc,0,'institution', 

54# # 'CSIRO Land and Water') ncdf4::ncatt_put(nc,0,'comment', '') 

55# # ncdf4::ncatt_put(nc,0,'source', '') catchment = paste(letters[1:9], 

56# # collapse='') ncdf4::ncatt_put(nc,0,'Catchment', catchment) 

57# # ncdf4::ncatt_put(nc,0,'title', paste('Rainfall Observations for', 

58# # catchment)) 

59 

60# #' Add a value to a global attribute of a netCDF file 

61# #' 

62# #' Add a value to a global attribute of a netCDF file 

63# #' 

64# #' @param nc an object 'ncdf4' 

65# #' @param attribute_name the name of the global attribute to add to 

66# #' @param attribute_value the value to pad 

67# #' @param sep separator to add between the existing value and the padded value. 

68# #' @export 

69# #' @import ncdf4 

70# pad_global_attribute(nc, attribute_name, attribute_value, sep = "\n") { 

71# attVal = "" 

72# a = ncdf4::ncatt_get(nc, 0, attribute_name) 

73# if (a$hasatt) { 

74# attVal = paste(a$value, sep) 

75# attVal = paste(attVal, attribute_value) 

76# } else { 

77# attVal = attribute_value 

78# } 

79# ncdf4::ncatt_put(nc, 0, attribute_name, as.character(attVal)) 

80# } 

81 

82 

83#' Define a set of global attributes for netCDF files. 

84#' 

85#' The conventions require a set of global attributes to be present, 

86#' see \url{https://github.com/jmp75/efts/blob/master/docs/netcdf_for_water_forecasting.md#global-attributes}. 

87#' This function is recommended to define these attributes. 

88#' 

89#' @param title text, a succinct description of what is in the dataset 

90#' @param institution text, Where the original data was produced 

91#' @param source text, published or web-based references that describe the data or methods used to produce it 

92#' @param catchment text, the catchment for which the data is created. White spaces are replaced with underscores 

93#' @param comment text, miscellaneous information 

94#' @param strict logical, if true perform extra checks on the input information 

95#' @export 

96#' @importFrom stringr str_replace_all 

97def create_global_attributes( 

98 title: str, 

99 institution: str, 

100 source: str, 

101 catchment: str, 

102 comment: str, 

103) -> dict[str, str]: 

104 """Creates STF global attributes. 

105 

106 Args: 

107 title (str): title 

108 institution (str): institution 

109 source (str): source 

110 catchment (str): catchment 

111 comment (str): comment 

112 

113 Raises: 

114 ValueError: Unexpected or insufficient information 

115 

116 Returns: 

117 dict[str, str]: _description_ 

118 """ 

119 # catchment info should not have white spaces (and why was that???) 

120 # catchment = 'Upper Murray River ' 

121 # catchment = stringr::str_replace_all(catchment, pattern='\\s+', '_') 

122 

123 if title == "": 

124 raise ValueError("Empty title is not accepted as a valid attribute") 

125 

126 return { 

127 TITLE_ATTR_KEY: title, 

128 INSTITUTION_ATTR_KEY: institution, 

129 SOURCE_ATTR_KEY: source, 

130 CATCHMENT_ATTR_KEY: catchment, 

131 COMMENT_ATTR_KEY: comment, 

132 } 

133 

134 

135# ######################################## 

136# # Below are functions not exported 

137# ######################################## 

138 

139# check_global_attributes(nc_attributes) 

140# { 

141# stopifnot(is.list(nc_attributes)) 

142# expected = mandatory_global_attributes 

143# present_attr = expected %in% names(nc_attributes) 

144# missing_attr = which(!present_attr) 

145# if(length(missing_attr) > 0) stop(paste("missing global attributes: ",paste(expected[missing_attr], collapse=","), sep=" ")) 

146# } 

147 

148# put_variable_attributes(data_var_def, nc) { 

149# a = data_var_def 

150# stopifnot("name" %in% names(a)) 

151# varname = a[["name"]] 

152# if ("attributes" %in% names(a)) { 

153# attribs = a[["attributes"]] 

154# for (attribute_name in names(attribs)) { 

155# ncdf4::ncatt_put(nc, varname, attribute_name, attribs[[attribute_name]]) 

156# } 

157# } 

158# }