kyoslib_py 5.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kyoslib_py/__init__.py ADDED
File without changes
@@ -0,0 +1,228 @@
1
+ import os
2
+
3
+ import pandas as pd
4
+
5
+ from kyoslib_py.kyos_api import call_kyos_api_v1
6
+
7
+
8
+ def write_curve_to_csv(curves, delTypes, grID, fullFileName):
9
+ """
10
+ Stores the forward curves in generalized data format on the disk in ./ForwardCurves
11
+ directory.
12
+
13
+ Args:
14
+ curves (dict): HTTP response body which provided by kyos_api.call_kyos_api_v1
15
+ delTypes (list): baseload:1, peak:2, offpeak:3
16
+ grID (int): granularity id of the requested forward curve(e.g. half-hour:1, hour:2, day:3, month:5)
17
+ fullFileName (str): full path of the file(e.g. "./ForwardCurves/ForwardCurveDaily_2_20200101")
18
+
19
+ Note:
20
+ The current implementation allows to store only data based on monthly granularity.
21
+
22
+ Examples:
23
+ >>> from kyoslib_py.forward_curve import write_curve_to_csv
24
+ >>> curves = {}
25
+ >>> data = {}
26
+ >>> month = {}
27
+ >>> baseload = [{'date':'2020-01-01', 'value':20.2}, {'date':'2020-02-01', 'value':30.3}]
28
+ >>> month['baseload'] = baseload
29
+ >>> data['month'] = month
30
+ >>> curves['data'] = data
31
+ >>> write_curve_to_csv(curves, [1, 2, 3], 5, "./ForwardCurves/ForwardCurveMonthlyDeliveryTypes_2_20200101")
32
+ """
33
+
34
+ if grID == 1: # half-hourly
35
+ return
36
+ elif grID == 2: # hourly
37
+ return
38
+ elif grID == 3: # daily
39
+ return
40
+ elif grID == 5: # monthly
41
+ curves_df = pd.DataFrame()
42
+ numDelType = len(delTypes)
43
+ # read dates from base load and store in the table, column name should be "0" for the date column
44
+ curves_df['0'] = [x['date'] for x in curves['data']['month']['baseload']]
45
+
46
+ for i in range(numDelType):
47
+ if delTypes[i] == 1:
48
+ curves_df[str(delTypes[i])] = [
49
+ x['value'] for x in curves['data']['month']['baseload']
50
+ ]
51
+ elif delTypes[i] == 2:
52
+ curves_df[str(delTypes[i])] = [
53
+ x['value'] for x in curves['data']['month']['peakload']
54
+ ]
55
+ elif delTypes[i] == 3:
56
+ curves_df[str(delTypes[i])] = [
57
+ x['value'] for x in curves['data']['month']['offpeak']
58
+ ]
59
+ # write monthly curves to csv
60
+ curves_df.to_csv(fullFileName, index=False)
61
+ return
62
+
63
+
64
+ def get_curve_api(fwdCurveID, granularityID, deliveryTypes, tradingDates, isCSVWrite):
65
+ """
66
+ Performs API requests to KYOS API and stores the curve inputs in a generalized format in CSV
67
+ files or returns a pandas.DataFrame.
68
+
69
+ Args:
70
+ fwdCurveID (int): id of the curve profile
71
+ granularityID (int): half-hour:1, hour:2, day:3, month:5
72
+ deliveryTypes (list|int): list of delivery type ids(int array), base load:1, peak:2, off-peak:3
73
+ tradingDates (list): list of trading dates(string array) e.g. ['2019-01-01', '2019-01-02', '2019-01-03']
74
+ isCSVWrite (bool): indicator of creating csv files, 0 or 1, we will provide a DataFrame in case of zero.
75
+
76
+ Returns:
77
+ (pandas.DataFrame): Contains all requested curves. If isCSVWrite equals 1 then the dataframe will be empty and
78
+ the curves will be saved as CSV files on the disk in directory ./ForwardCurves.
79
+
80
+ Note:
81
+ KYOS API provides the curves with the daylight saving switches for the half-hourly and hourly curves.
82
+ KYOS API supports base load, peak and off-peak delivery types only for monthly granularity.
83
+
84
+ Examples:
85
+ >>> from kyoslib_py.forward_curve import get_curve_api
86
+ >>> arg = {'fwdCurveID': 4, 'granularityID': 5, 'deliveryTypes': [1, 2, 3],
87
+ >>> 'tradingDates': ['2019-01-01', '2019-01-02'], 'isCSVWrite': 1}
88
+ >>> curves_df = get_curve_api(**arg)
89
+ >>> arg = {'fwdCurveID': 4, 'granularityID': 5, 'deliveryTypes': 1 ,
90
+ >>> 'tradingDates': '2019-01-01', 'isCSVWrite': 1}
91
+ >>> curves_df2 = get_curve_api(**arg)
92
+ """
93
+ # Initialize output directory
94
+ curDir = os.getcwd()
95
+ outputDir = os.path.join(curDir, 'ForwardCurves')
96
+ if isCSVWrite and (not os.path.exists(outputDir)):
97
+ os.mkdir(outputDir)
98
+ forward_curves_df = pd.DataFrame()
99
+ # ################################ INPUT VALIDATION ###########################################
100
+ # Check the granularity input
101
+ if granularityID == 1:
102
+ fileName = f"ForwardCurveHalfHourlyDST_{fwdCurveID}_"
103
+ granularity = 'half_hour'
104
+ elif granularityID == 2:
105
+ fileName = f"ForwardCurveHourlyDST_{fwdCurveID}_"
106
+ granularity = 'hour'
107
+ elif granularityID == 3:
108
+ fileName = f"ForwardCurveDaily_{fwdCurveID}_"
109
+ granularity = 'day'
110
+ elif granularityID == 5:
111
+ fileName = f"ForwardCurveMonthlyDeliveryTypes_{fwdCurveID}_"
112
+ granularity = 'month'
113
+ else:
114
+ print('The granularity id:' + str(granularityID) + ' is not supported in KYOS API!!!')
115
+ return forward_curves_df
116
+ # in case of empty delivery type after the cleaning process, initialize base load in the list
117
+ if deliveryTypes is None:
118
+ deliveryTypes = [1]
119
+
120
+ # Check the delivery type input, deliveryTypes should be a list
121
+ if type(deliveryTypes) != list:
122
+ deliveryTypes = [deliveryTypes]
123
+ if len(deliveryTypes) == 0:
124
+ deliveryTypes.append(1) # in case of empty delivery type list, import the base load curve
125
+ else:
126
+ # remove the unsupported delivery types from the list
127
+ deliveryTypes = [
128
+ deliveryTypes for deliveryTypes in deliveryTypes if deliveryTypes in [1, 2, 3]
129
+ ]
130
+
131
+ # Check tradingDates, it should be provided as a list
132
+ if type(tradingDates) != list:
133
+ tradingDates = [tradingDates]
134
+
135
+ # ########################################### IMPORT CURVES #######################################################
136
+ numTradDays = tradingDates.__len__()
137
+ for i in range(numTradDays):
138
+ tradingDate_i = tradingDates[i]
139
+ query = f"/curves/results/{fwdCurveID}/{tradingDate_i}?filter[granularity]={granularity}"
140
+
141
+ status, data = call_kyos_api_v1(query)
142
+ if 200 >= status < 300:
143
+ if isCSVWrite == 1: # in this case, we will store the curves on disk per trading dates
144
+ fullName = os.path.join(
145
+ outputDir, f"{fileName}{tradingDate_i.replace('-', '')}.csv"
146
+ )
147
+ write_curve_to_csv(data, deliveryTypes, granularityID, fullName)
148
+ else: # in this case, we will store the curves in a dataframe
149
+ curves_df_i = pd.DataFrame()
150
+ numDelType = len(deliveryTypes)
151
+ # update curve id and trading dates column
152
+ if granularityID == 1: # half-hourly
153
+ if data.get('data'):
154
+ numHhours = data['data']['half_hour']['baseload'].__len__()
155
+ curves_df_i['curve_id'] = [fwdCurveID for _ in range(numHhours)]
156
+ curves_df_i['trading_dates'] = [tradingDate_i for _ in range(numHhours)]
157
+
158
+ # read dates from base load and store in the table as delivery dates
159
+ curves_df_i['delivery_dates'] = [
160
+ x['date'] for x in data['data']['half_hour']['baseload']
161
+ ]
162
+ curves_df_i['baseload'] = [
163
+ x['value'] for x in data['data']['half_hour']['baseload']
164
+ ]
165
+ else:
166
+ print('There is no ' + granularity + ' curve for this profile!')
167
+ return forward_curves_df
168
+ elif granularityID == 2: # hourly
169
+ if data.get('data'):
170
+ numHours = data['data']['hour']['baseload'].__len__()
171
+ curves_df_i['curve_id'] = [fwdCurveID for _ in range(numHours)]
172
+ curves_df_i['trading_dates'] = [tradingDate_i for _ in range(numHours)]
173
+
174
+ # read dates from base load and store in the table as delivery dates
175
+ curves_df_i['delivery_dates'] = [
176
+ x['date'] for x in data['data']['hour']['baseload']
177
+ ]
178
+ curves_df_i['baseload'] = [
179
+ x['value'] for x in data['data']['hour']['baseload']
180
+ ]
181
+ else:
182
+ print('There is no ' + granularity + ' curve for this profile!')
183
+ return forward_curves_df
184
+ elif granularityID == 3: # daily
185
+ if data.get('data'):
186
+ numDays = data['data']['day']['baseload'].__len__()
187
+ curves_df_i['curve_id'] = [fwdCurveID for _ in range(numDays)]
188
+ curves_df_i['trading_dates'] = [tradingDate_i for _ in range(numDays)]
189
+
190
+ # read dates from base load and store in the table as delivery dates
191
+ curves_df_i['delivery_dates'] = [
192
+ x['date'] for x in data['data']['day']['baseload']
193
+ ]
194
+ curves_df_i['baseload'] = [
195
+ x['value'] for x in data['data']['day']['baseload']
196
+ ]
197
+ else:
198
+ print('There is no ' + granularity + ' curve for this profile!')
199
+ return forward_curves_df
200
+ elif granularityID == 5: # monthly
201
+ numMonths = data['data']['month']['baseload'].__len__()
202
+ curves_df_i['curve_id'] = [fwdCurveID for _ in range(numMonths)]
203
+ curves_df_i['trading_dates'] = [tradingDate_i for _ in range(numMonths)]
204
+
205
+ # read dates from base load and store in the table as delivery dates
206
+ curves_df_i['delivery_dates'] = [
207
+ x['date'] for x in data['data']['month']['baseload']
208
+ ]
209
+ for i in range(numDelType):
210
+ if deliveryTypes[i] == 1:
211
+ curves_df_i['baseload'] = [
212
+ x['value'] for x in data['data']['month']['baseload']
213
+ ]
214
+ elif deliveryTypes[i] == 2:
215
+ curves_df_i['peak'] = [
216
+ x['value'] for x in data['data']['month']['peakload']
217
+ ]
218
+ elif deliveryTypes[i] == 3:
219
+ curves_df_i['offpeak'] = [
220
+ x['value'] for x in data['data']['month']['offpeak']
221
+ ]
222
+
223
+ forward_curves_df = pd.concat([forward_curves_df, curves_df_i])
224
+ print(query + ' Imported!')
225
+ else:
226
+ print(query + ' could not be imported!')
227
+
228
+ return forward_curves_df
@@ -0,0 +1,388 @@
1
+ import csv
2
+ import json
3
+ import os
4
+
5
+ import numpy as np
6
+ import plotly.express as px
7
+ from plotly.io import write_json as plotly_write_json
8
+
9
+
10
+ class PlatformGraphs(object):
11
+ """
12
+ Handle the mapping of plotly graphs to a format which can be displayed by the KYOS platform.
13
+ There can be at most one instance of this class (singleton design pattern).
14
+ """
15
+
16
+ _instance = None # keep instance reference
17
+
18
+ def __new__(cls):
19
+ if not cls._instance:
20
+ cls._instance = super(PlatformGraphs, cls).__new__(cls)
21
+ # initialize output directory for platform graphs
22
+ output_location = os.path.join(os.getcwd(), 'Output', 'PlatformDisplay')
23
+ if not os.path.exists(output_location):
24
+ os.makedirs(output_location)
25
+ cls._instance.output_location = output_location
26
+ return cls._instance
27
+
28
+ def save2disk(
29
+ self,
30
+ fig,
31
+ filename: str,
32
+ xanchor='left',
33
+ yanchor='bottom',
34
+ orientation='h',
35
+ x=0.1,
36
+ y=-0.075,
37
+ ):
38
+ """
39
+ Save a plotly graph object in a json format and in a proper location on the KYOS servers.
40
+
41
+ Args:
42
+ fig (plotly.graph_objects): a fully built plotly figure
43
+ filename (str): under what filename should the graph be saved on the server's hard-disk.
44
+ Note that the filename plays a role in the order of displaying graphs in the fornt end.
45
+ xanchor (str): (Optional) One of ( "auto" | "left" | "center" | "right" ) Sets the title's horizontal
46
+ alignment with respect to its x position. "left" means that the title starts at x. Default:"left"
47
+ yanchor (str): (Optional) One of ( "auto" | "top" | "middle" | "bottom" ) Sets the title's vertical
48
+ alignment with respect to its y position. "top" means that the title's cap line is at y. Default:"bottom"
49
+ orientation (str): (Optional) one of ( "v" | "h" ). Sets the orientation of the legend. Default:"h"
50
+ x (float): (Optional) number between or equal to -2 and 3 Sets the x position (in normalized coordinates)
51
+ of the legend. KYOS Platform Defaults to 0.1
52
+ y (float): (Optional) number between or equal to -2 and 3 Sets the y position (in normalized coordinates)
53
+ of the legend. KYOS Platform Defaults to -0.075
54
+
55
+ Examples:
56
+ >>> graph_object = PlatformGraphs()
57
+ >>> fig = px.histogram()
58
+ >>> graph_object.save2disk(fig, filename="001_option_value")
59
+ """
60
+ # legend style same over the whole platform
61
+ # -> styling can be moved to a separate method
62
+ fig.update_layout(
63
+ legend={
64
+ 'xanchor': xanchor,
65
+ 'yanchor': yanchor,
66
+ 'orientation': orientation,
67
+ 'x': x,
68
+ 'y': y,
69
+ }
70
+ )
71
+ fig.update_layout(
72
+ plot_bgcolor="#FFF", # Sets background color to white
73
+ xaxis=dict(
74
+ linecolor="#BCCCDC", # Sets color of X-axis line
75
+ showgrid=False, # Removes X-axis grid lines
76
+ ),
77
+ yaxis=dict(
78
+ linecolor='gray',
79
+ showgrid=True, # Keep Y-axis grid lines
80
+ ),
81
+ )
82
+
83
+ full_path = os.path.join(self.output_location, filename + "_plotly.json")
84
+ plotly_write_json(fig, full_path)
85
+
86
+
87
+ def make_platform_table(
88
+ df, table_name, bold_row_name=True, bold_column_name=True, columns_names=None
89
+ ):
90
+ """
91
+ Function which outputs a pandas dataframe in a format which can be displayed in the KYOS platform.
92
+
93
+ Args:
94
+ df (pandas.Dataframe): A single row index is allowed. Multiple column indexes are allowed.
95
+ bold_row_name (bool): Display the row name in bold font when showing it in the platform front-end
96
+ bold_column_name (bool): Display the column name in bold font when showing it in the platform front-end
97
+ columns_names (None|list): None: use the column names of the dataframe | list of list: user defined columns names (should include name for the row index as well)
98
+
99
+ Notes:
100
+ The data in the dataframe saved in a csv file in the desired format.
101
+
102
+ Examples:
103
+ >>> make_platform_table(data_df, '001_Option_Value', bold_column_name=True)
104
+ """
105
+ current_dir = os.path.dirname(os.path.realpath('__file__'))
106
+ # create output directory
107
+ output_dir = os.path.join(current_dir, 'Output/PlatformDisplay/')
108
+ os.makedirs(output_dir, exist_ok=True)
109
+
110
+ values = df.values.tolist()
111
+
112
+ # attach row names to the values
113
+ # currently only a single row name index is supported
114
+ all_rows = df.index.values.tolist()
115
+ n_row_indx = len(all_rows)
116
+ for r in range(n_row_indx):
117
+ name = all_rows[r]
118
+ if bold_row_name == True and name != "":
119
+ # add a tag to display the column name as bold
120
+ name = "<b>" + name.replace('_', ' ') + "</b>"
121
+ values[r].insert(0, name)
122
+
123
+ # Generate columns names consistent with the platform display format
124
+ if columns_names == None:
125
+ all_columns = df.columns.values.tolist()
126
+ all_col_names = []
127
+ if type(all_columns[0]) == str:
128
+ n_col_indx = 1
129
+ else: # tuple of all column indexes' name
130
+ n_col_indx = len(all_columns[0])
131
+
132
+ for i in range(n_col_indx):
133
+ col_names = [""] # currently only a single row name indexation is supported
134
+ unique_name = None
135
+ for col in all_columns:
136
+ if n_col_indx == 1:
137
+ name = col # col is just a string name
138
+ else:
139
+ name = str(col[i]) # column is a tuple of string names
140
+
141
+ if unique_name is not None and name == unique_name:
142
+ # a dataframe outputs the same name for a column when we have multi-indexing
143
+ # to display properly in the platform we drop the repeating names
144
+ name = ""
145
+ else:
146
+ unique_name = name
147
+
148
+ if bold_column_name == True and name != "":
149
+ # add a tag to display the column name as bold
150
+ name = "<b>" + name + "</b>"
151
+ col_names.append(name)
152
+ all_col_names.append(col_names)
153
+ else:
154
+ n_col_rows = len(columns_names[0])
155
+ all_col_names = []
156
+ for i in range(n_col_rows):
157
+ col_names = [x[i] for x in columns_names]
158
+ all_col_names.append(col_names)
159
+
160
+ with open(output_dir + table_name + ".csv", "w") as f:
161
+ writer = csv.writer(f)
162
+ writer.writerows(all_col_names)
163
+ with open(output_dir + table_name + ".csv", "a") as f:
164
+ writer = csv.writer(f)
165
+ writer.writerows(values)
166
+
167
+
168
+ def make_platform_histogram(
169
+ values, values_names, n_bins='auto', title=' ', output_filename='name'
170
+ ):
171
+ """
172
+ Build a histogram based on one or more value series. The histogram will be displayed dynamically in the
173
+ Kyos Analytical Platform.
174
+
175
+ Args:
176
+ values (numpy.ndarray): a histogram is built for each value series.
177
+ The min/max of the histogram buckets is based on the smallest/biggest element of all series.
178
+ [shape = (n_rows, n_series)]
179
+ values_names (list): a list of string names for each series.
180
+ [len = n_series]
181
+ n_bins (int): how many bins should be used in the histogram.
182
+ title (string): title of the histogram
183
+ output_filename (string): beginning of the name of the output json file. It can be used to order how graphs are
184
+ displayed in the platform. Graph with start of the name "001_" will be displayed first.
185
+
186
+ Note:
187
+ The histogram graph is build using the "Highcharts" package. For more info refer to [HighCharts](https://www.highcharts.com/demo/column-basic)
188
+
189
+ Examples:
190
+ >>> make_platform_histogram(values=values, values_names=['Value'],
191
+ >>> title='Total Option Value (EUR)',
192
+ >>> n_bins=20, output_filename='001_option_value')
193
+ """
194
+ # find bin edges based on all value series.
195
+ bin_edges = np.histogram_bin_edges(values, bins=n_bins, range=None, weights=None)
196
+ bin_means = list()
197
+ for b in range(len(bin_edges[:-1])):
198
+ bin_means.append((bin_edges[b] + bin_edges[b + 1]) / 2)
199
+
200
+ # find the frequency histogram per a single series
201
+ series = []
202
+ n_series = values.shape[1]
203
+ for i in range(n_series):
204
+ hist, bin_edges_out = np.histogram(values[:, i], bins=bin_edges)
205
+ hist_frequency = hist / hist.sum() * 100
206
+ hist_frequency = hist_frequency.tolist()
207
+ series.append({'name': values_names[i], 'data': hist_frequency})
208
+
209
+ y_label = 'Frequency'
210
+ column_chart = {
211
+ 'chart': {'type': 'column'},
212
+ 'title': {'text': title},
213
+ 'subtitle': {'text': ' '},
214
+ 'xAxis': {
215
+ 'labels': {'format': '{value:,.0f}'},
216
+ 'categories': bin_means,
217
+ 'crosshair': 'true',
218
+ },
219
+ 'yAxis': {
220
+ 'labels': {'format': '{value} %'},
221
+ 'min': 0,
222
+ 'title': {
223
+ 'text': y_label,
224
+ },
225
+ },
226
+ 'tooltip': {
227
+ 'headerFormat': ' ',
228
+ 'pointFormat': '<p><span style="color:{series.color}">&#x25cf;</span> <b>{series.name}: </b>{point.y:.1f} %</p>',
229
+ 'shared': 'true',
230
+ 'useHTML': 'true',
231
+ },
232
+ 'credits': {'text': 'Kyos Energy Consulting', 'href': 'http://www.kyos.com'},
233
+ 'plotOptions': {'column': {'pointPadding': 0, 'borderWidth': 0}},
234
+ 'series': series,
235
+ }
236
+ # output chart to json
237
+ with open('Output/PlatformDisplay/' + output_filename + '_chart.json', 'w') as outfile:
238
+ json.dump(column_chart, outfile)
239
+
240
+
241
+ def make_bar_column_chart(
242
+ values,
243
+ values_names,
244
+ is_stacked=False,
245
+ x_axis=None,
246
+ title=' ',
247
+ y_axis_title='values',
248
+ output_filename='name',
249
+ unit_name='unit',
250
+ ):
251
+ """
252
+ Build a bar column chart based on one or more value series. The chart will be displayed dynamically in the
253
+ Kyos Analytical Platform.
254
+
255
+ Args:
256
+ values (numpy.ndarray): y axis values
257
+ [shape = (n_rows, n_series)]
258
+ values_names (list): a list of string names for each series.
259
+ [len = n_series]
260
+ is_stacked (bool): indicator for chart type. basic column and stacked column chart supported
261
+ False: Basic column chart
262
+ True: Stacked column chart
263
+ x_axis (None|list): list of x-axis values
264
+ None: integer values will be used [1,2,3 .......]
265
+ list: user defined x axis names (e.g. dates)
266
+ title (string): title of the chart
267
+ y_axis_title (string): title of the y-axis
268
+ output_filename (string): beginning of the name of the output json file. It can be used to order how graphs are
269
+ displayed in the platform. Graph with start of the name "001_" will be displayed first.
270
+ unit_name (string): unit name of the values
271
+
272
+ Note:
273
+ The histogram graph is build using the "Highcharts" package. For more info refer to
274
+ [HighCharts](https://www.highcharts.com/demo/column-basic)
275
+
276
+ Examples:
277
+ >>> make_bar_column_chart(values=np.zeros((2,2)), values_names=['series_1', 'series_2'],is_stacked=True,
278
+ >>> x_axis=['2019-01-01', '2019-01-02'], title='Daily Positions', y_axis_title='Positions',
279
+ >>> output_filename='001_option_value', unit_name='Lots')
280
+ """
281
+
282
+ if x_axis is None:
283
+ x_axis = []
284
+ y_axis_title = y_axis_title + ' (' + unit_name + ')'
285
+ # Check chart type and create plot options
286
+ plot_options = {}
287
+ if is_stacked:
288
+ plot_options = {'column': {'stacking': 'normal'}}
289
+ # covert series to list
290
+ series = []
291
+ n_series = values.shape[1]
292
+ for i in range(n_series):
293
+ series_i = values[:, i].tolist()
294
+ series.append({'name': values_names[i], 'data': series_i})
295
+
296
+ bar_chart = {
297
+ 'chart': {'type': 'column'},
298
+ 'title': {'text': title},
299
+ 'xAxis': {'categories': x_axis},
300
+ 'yAxis': {'min': 0, 'title': {'text': y_axis_title}},
301
+ 'tooltip': {
302
+ 'headerFormat': '<span style="font-size:10px">{point.key}</span><table>',
303
+ 'pointFormat': '<tr><td style="color:{series.color};padding:0">{series.name}: </td>'
304
+ + '<td style="padding:0"><b>{point.y:.1f} '
305
+ + unit_name
306
+ + '</b></td></tr>',
307
+ 'footerFormat': '</table>',
308
+ 'shared': 'true',
309
+ 'useHTML': 'true',
310
+ },
311
+ 'credits': {'text': 'Kyos Energy Consulting', 'href': 'http://www.kyos.com'},
312
+ 'plotOptions': plot_options,
313
+ 'series': series,
314
+ }
315
+
316
+ # output chart to json
317
+ with open('Output/PlatformDisplay/' + output_filename + '_chart.json', 'w') as outfile:
318
+ json.dump(bar_chart, outfile)
319
+
320
+
321
+ def make_basic_line_chart(
322
+ values,
323
+ values_names,
324
+ x_axis=None,
325
+ title=' ',
326
+ y_axis_title='values',
327
+ output_filename='name',
328
+ unit_name='unit',
329
+ ):
330
+ """
331
+ Build a bar column chart based on one or more value series. The chart will be displayed dynamically in the
332
+ Kyos Analytical Platform.
333
+
334
+ Args:
335
+ values (numpy.ndarray): y axis values
336
+ [shape = (n_rows, n_series)]
337
+ values_names (list): a list of string names for each series.
338
+ [len = n_series]
339
+ x_axis (None|list): list of x-axis values
340
+ None: integer values will be used [1,2,3 .......]
341
+ list: user defined x axis names (e.g. dates)
342
+ title (string): title of the chart
343
+ y_axis_title (string): title of the y-axis
344
+ output_filename (string): beginning of the name of the output json file. It can be used to order how graphs are
345
+ displayed in the platform. Graph with start of the name "001_" will be displayed first.
346
+ unit_name (string): unit name of the values
347
+
348
+ Note:
349
+ The histogram graph is build using the "Highcharts" package. For more info refer to
350
+ [HighCharts](https://www.highcharts.com/demo/column-basic)
351
+
352
+ Examples:
353
+ >>> make_basic_line_chart(values=np.zeros((2,2)), values_names=['series_1', 'series_2'],
354
+ >>> x_axis=['2019-01-01', '2019-01-02'], title='Daily Positions', y_axis_title=' ',
355
+ >>> output_filename='001_option_value', unit_name='Lots')
356
+ """
357
+
358
+ if x_axis is None:
359
+ x_axis = []
360
+ y_axis_title = y_axis_title + ' (' + unit_name + ')'
361
+ # covert series to list
362
+ series = []
363
+ n_series = values.shape[1]
364
+ for i in range(n_series):
365
+ series_i = values[:, i].tolist()
366
+ series.append({'name': values_names[i], 'data': series_i})
367
+
368
+ line_chart = {
369
+ 'title': {'text': title},
370
+ 'xAxis': {'categories': x_axis},
371
+ 'yAxis': {'title': {'text': y_axis_title}},
372
+ 'tooltip': {
373
+ 'headerFormat': '<span style="font-size:10px">{point.key}</span><table>',
374
+ 'pointFormat': '<tr><td style="color:{series.color};padding:0">{series.name}: </td>'
375
+ + '<td style="padding:0"><b>{point.y:.1f} '
376
+ + unit_name
377
+ + '</b></td></tr>',
378
+ 'footerFormat': '</table>',
379
+ 'shared': 'true',
380
+ 'useHTML': 'true',
381
+ },
382
+ 'credits': {'text': 'Kyos Energy Consulting', 'href': 'http://www.kyos.com'},
383
+ 'series': series,
384
+ }
385
+
386
+ # output chart to json
387
+ with open('Output/PlatformDisplay/' + output_filename + '_chart.json', 'w') as outfile:
388
+ json.dump(line_chart, outfile)