@@ -71,6 +71,8 @@ def write(self, options: dict = {}, data: dict = None) -> str:
7171
7272 if 'Feature' in type or 'features' in data :
7373 return self ._write_from_geojson (options , data )
74+ elif 'Coverage' in type or 'coverages' in data :
75+ return self ._write_from_covjson (options , data )
7476
7577 def _write_from_geojson (
7678 self , options : dict = {}, data : dict = None , is_point = False
@@ -135,7 +137,79 @@ def _add_feature(
135137 LOGGER .error (err )
136138 raise FormatterSerializationError ('Error writing CSV output' )
137139
140+ def _write_from_covjson (
141+ self , options : dict = {}, data : dict = None
142+ ) -> str :
143+ """
144+ Generate CovJSON data in CSV format
145+
146+ :param options: CSV formatting options
147+ :param data: dict of CovJSON data
148+
149+ :returns: string representation of format
150+ """
151+ LOGGER .debug ('Processing CovJSON data for CSV output' )
152+ units = {}
153+ for p , v in data ['parameters' ].items ():
154+ unit = v ['unit' ]['symbol' ]
155+ if isinstance (unit , dict ):
156+ unit = unit .get ('value' )
157+
158+ units [p ] = unit
159+
160+ fields = ['parameter' , 'datetime' , 'value' , 'unit' , 'x' , 'y' ]
161+ LOGGER .debug (f'CSV fields: { fields } ' )
162+ output = io .StringIO ()
163+ writer = csv .DictWriter (output , fields )
164+ writer .writeheader ()
165+
166+ if data ['type' ] == 'Coverage' :
167+ is_point = 'point' in data ['domain' ]['domainType' ].lower ()
168+ self ._add_coverage (writer , units , data , is_point )
169+ else :
170+ [
171+ self ._add_coverage (writer , units , coverage , True )
172+ for coverage in data ['coverages' ]
173+ if 'point' in coverage ['domain' ]['domainType' ].lower ()
174+ ]
138175 return output .getvalue ().encode ('utf-8' )
139176
177+ @staticmethod
178+ def _add_coverage (
179+ writer : csv .DictWriter , units : dict , data : dict , is_point : bool = False
180+ ) -> None :
181+ """
182+ Add coverage data to CSV writer
183+
184+ :param writer: CSV DictWriter
185+ :param units: dict of parameter units
186+ :param data: dict of CovJSON coverage data
187+ :param is_point: whether the coverage is a point coverage
188+ """
189+
190+ if is_point is False :
191+ LOGGER .warning ('Non-point coverages not supported for CSV output' )
192+ return
193+
194+ axes = data ['domain' ]['axes' ]
195+ time_range = range (len (axes ['t' ]['values' ]))
196+
197+ try :
198+ [
199+ writer .writerow ({
200+ 'parameter' : parameter ,
201+ 'datetime' : axes ['t' ]['values' ][time_value ],
202+ 'value' : data ['ranges' ][parameter ]['values' ][time_value ],
203+ 'unit' : units [parameter ],
204+ 'x' : axes ['x' ]['values' ][- 1 ],
205+ 'y' : axes ['y' ]['values' ][- 1 ]
206+ })
207+ for parameter in data ['ranges' ]
208+ for time_value in time_range
209+ ]
210+ except ValueError as err :
211+ LOGGER .error (err )
212+ raise FormatterSerializationError ('Error writing CSV output' )
213+
140214 def __repr__ (self ):
141215 return f'<CSVFormatter> { self .name } '
0 commit comments