この記事は、データサイエンティストでDelphi開発者のMax Kleiner氏の投稿です。彼は、Maxboxの作者であり、このツールを自身のサイトで「コンパイル済みオブジェクトをベースとしたスクリプトツール」と紹介しています。記事では、RAD Studio / Delphiを用いてWindowsソフトウェアを開発し、HTTPリクエストによって取得したJSONオブジェクトを使って、集積ガス貯蔵施設の貯蔵量データをグラフやチャートで可視化する方法を説明しています。
Table of Contents
貯蔵ガスのデータをAGSIデータセットのタイムラインとして可視化
「データサイエンティストにはさまざまな種類がある。その中で最高なのはデータに取り組む人だ。」
このデータサイエンスチュートリアルでは、AGISと呼ばれるデータストレージとタイムラインでの可視化について説明しています。AGISは、Aggregated Gas Storage Inventoryの略で、集積ガス貯蔵施設の貯蔵量のデータです。データプロバイダーから新しいサービスが発表されたり更新があり、Webサイトにその情報が掲載されるたびに、そのデータを最新に保つことが可能になります。
GIE(Gas Infrastructure Europe)は、Storage MapやStorage Investment Databaseといった関連情報も、https://www.gie.eu/publications/maps/ で提供しています。
データチャート(グラフ)の表示
タイムラインデータを可視化したグラフは、以下のようになります。

データのダウンロードとグラフ作成に使用したコンポーネント
このツールでは、WinHttp.WinHttpRequest、JSONObjects、そしてTEEChartsライブラリを使用して、プロットのロードとテストを行っています。APIキーも必要になるため、以下のサイトからあらかじめ入手しておきます。
データが表現するもの
取得するデータは、日ごとのガス貯蔵量を表します。データは毎日、19:30と23:00(中央ヨーロッパ時間)に更新されます。コードの詳細を説明する前に、スクリプトの主要な部分を以下に示します。
plotform:= getForm2(1400, 600, clsilver, 'Sciplot4maXbox'); plotform.icon.loadfromresourcename(hinstance,'ZHISTOGRAM'); HttpResponse:= getEnergyStreamJSON2(URL_AGSIAPI2,'DE,2022-01-03,150',AGSI_APIKEY); JSON2Plot(plotform, letGenerateJSON2(HttpResponse));
コード概要
コードのメイン部分では、フォームを生成し、API呼び出しとデータのプロットを行っています。
GIEでは、AGSIおよびALSI Transparency Publication Platformsで、API(Application Programming Interface)サービスを提供しています。
APIアクセスを用いれば、ユーザーはAGSIおよびALSIのWebサイトをバイパスして、データを直接かつ継続的に取得できます。Webサイトから各データセットを個別にダウンロードすることなく、必要に応じてデータ抽出、フィルタリング、集計、サブセット生成が可能になります。APIのデータエクスポートフォーマットは、JSONです。以下は、150日分のサブセットデータです。

グラフに描画するデータ
公開されているデータセットは、ACERに提供されているEICコードマッピングテーブルをベースとしています。ストレージデータは、国別、会社別に集計されます。
API呼び出しでは、国、開始日、日数を指定します。
getEnergyStreamJSON2(URL_AGSIAPI2,'DE,2022-01-03,150',AGSI_APIKEY);
データセットは、Excel、CSV,JSON形式でもダウンロードできます。このレポートでは、集計ビューを表示していますが、会社ごと、貯蔵施設ごとの個別データセットにもアクセスできます。
データ取得のためのAPI呼び出し
では、API呼び出しの方法から紹介します。
HttpResponse:= getEnergyStreamJSON2(URL_AGSIAPI2,'DE,2022-01-03,150',AGSI_APIKEY);
このコマンドにより、WinHttp.WinHttpRequestを実行します。失敗すると、以下のような例外が複数生成されます。
Exception: WinHttp.WinHttpRequest: The data necessary to complete this operation is not yet available; or you missed a valid key:
AGSIPost: Failed at getting response:403{
"error": {
"code": 403,
"message": "The request is missing a valid API key.",
"status": "PERMISSION_DENIED"
}}
面白いのは、例外がJSON形式になっている点です。
Be careful, also, to expose your key as I get from Git: GitGuardian has detected the following Google API Key exposed within your GitHub account.
APIでJSONデータを取得する
Next is the formatting of the get-call with a valid API-key request in the function energyStream()関数で、有効なAPIキーリクエストを使用してGET呼び出しを書式化します。
function getEnergyStreamJSON2(AURL, feedstream, aApikey:string): string;
...
encodURL:= Format(AURL,[HTTPEncode(asp[0]),(asp[1]),asp[2]]);
writeln(encodurl) //debug
hr:= httpRq.Open('GET', encodURL, false);
httpRq.setRequestheader('user-agent',USERAGENTE);
httpRq.setRequestheader('x-key',aAPIkey);
...
ところで、content-typeはどこで設定するのでしょうか。私の知る限り、content-typeを設定する箇所は、Webリクエストの2箇所のみです。
- クライアントが、サーバーに送信するbodyに対して、content-typeを設定(つまり、GETまたはPOSTで設定)
- サーバーが、レスポンスに対してcontent-typeを設定
利用可能なContent-Typeを明示する
ペイロードボディを含むメッセージを生成する送信元は、そのcontent-typeが不明でない限り、Content-Typeヘッダフィールドを生成する必要があります。それ以外の場合、503503 - Service Unavailable という応答で取得に失敗します。
('headers={"Content-Type":"application/json"}')
httpRq.setRequestheader('Content-Type',application/json);
つまり、content-type HTTPヘッダは、PUTおよびPOSTでのみ設定する必要があるということです。GETリクエストでは、クライアントが理解できるコンテンツタイプを示す「Accept」ヘッダを含めることができます。サーバーは、この情報を用いて、返信するコンテンツ タイプを決定できます。
オプションで、TALWinInetHttpClientを用いることもできます。これは、使いやすいWinInetベースのプロトコルで、HTTPSをサポートしています。このHTTPクライアントコンポーネントは、HTTPプロトコルを介してWebでデータの送信および取得ができます。
function TALHTTPClient_Get(aUrl: AnsiString;
feedstream, aApikey: string): string;
Var
LHttpClient: TALWininetHttpClient;
asp: TStringArray;
begin
LHttpClient:= TALWininetHttpClient.create;
asp:= splitStr(feedstream,',');
LHttpClient.url:= Format(AURL,[HTTPEncode(asp[0]),(asp[1]),asp[2]]);
LHttpClient.RequestMethod:= HTTPmt_Get; //HTTPrm_Post;
LHttpClient.RequestHeader.UserAgent:=USERAGENTE;
//LHttpClient.RequestHeader.CustomHeaders:=
LHttpClient.RequestHeader.RawHeaderText:='x-key:'+aAPIkey;
try
result:= LHttpClient.Get1(LHttpClient.url); //overload;
finally
LHttpClient.Free;
end;
end;
JSONレスポンスをグラフで使用できるデータに変換する
AGSIでは、欠落したデータも不完全なデータも表示されます。次に行うのは、取得したJSONデータをTJSONObjectを使って、プロット用に変換することです。
function letGenerateJSON2(HttpRqresponseText: string): TJSONArray;
var jo: TJSONObject;
begin
jo:= TJSONObject.Create4(HttpRqresponseText);
try
//writeln(jo.getstring('data'));
writeln(itoa(jo.getjsonarray('data').getjsonobject(0).length))
writeln(itoa(jo.getjsonarray('data').length))
result:= jo.getjsonarray('data');
//write out to check
for it:= 0 to result.length-1 do
writeln(result.getjsonobject(it).getstring('gasDayStart')+':'+
result.getjsonobject(it).getstring('injection'));
except
writeln('EJson: '+ExceptiontoString(exceptiontype, exceptionparam));
end;
end;
関数の戻り値として取得できるこのJSON配列を、次のプロット処理に渡します。
procedure JSON2Plot(form1: TForm; jar: TJSONArray);
var chart1: TChart;
cnt: integer; sumup,tmp2,tmp: double; gday: string;
begin
form1.onclose:= @Form_CloseClick;
chart1:= ChartInjector(form1);
sumup:=0; tmp2:=0; tmp:=0;
try
for cnt:= 0 to jar.length-1 do begin
//writeln(locate.getjsonobject(it).getstring('gasDayStart')+':'+
tmp:= jar.getjsonobject(jar.length-1-cnt).getdouble('injection');
tmp2:= jar.getjsonobject(jar.length-1-cnt).getdouble('full');
sumup:= sumup+tmp;
gday:= jar.getjsonobject(jar.length-1-cnt).getstring('gasDayStart');
chart1.Series[0].Addxy(cnt,tmp,gday,clgreen);
chart1.Series[1].Addxy(cnt,tmp2,'',clred);
chart1.Series[2].Addxy(cnt,jar.getjsonobject(jar.length-1-cnt).getdouble('withdrawal'),'',clyellow);
end;
except
writeln('EPlot: '+ExceptiontoString(exceptiontype, exceptionparam));
end;
PrintF('Landrange %d: Injection sum: %.2f',[jar.length-1,sumup]);
end;
グラフの系列に含まれるデータ
グラフには、4つのデータ系列をプロットします(タイムラインを含む)。
- 注入量(ガス日あたり)
- 充足率 – Storage / WGV(in%)
- 放出量(ガス日あたり – 2桁精度)
- ガス日(レポートの開始ガス日)
時系列は、ガス日単位です。
「ガス日」とは、 UTCで5:00~5:00(夏時間では、4:00~4:00)を意味します。ガス日は、ヨーロッパ中央時間(CET)の場合、UTC+1、夏時間(CEST)の場合UTC+2となります(定義: CAM Network Code Specificationsを参照)。
データ取得用APIにアクセスする方法
APIアクセスは、RESTライクなインターフェイス (Representational State Transfer) で提供され、上述したレスポンスヘッダにcontent-typeを含む、JSON形式でデータベースリソースを公開しています。

他言語向けのデータアクセス方法
データサイエンスビジョンのコードには、使用例を示すサンプルが添付されており、Python3、Delphi、Jupyter-Notebook、Object Pascal、maXbox4で使用できます。なお、このAPIサービスは無料公開されています。このプラットフォーム上で現在利用可能なデータのみにアクセスできます。
メモ:システムから直接データを抽出するには、ブラウザで以下のリンクを直接クリックしてください。
https://agsi.gie.eu/api?type=eu
GIEデータAPIに関する情報
GIEでは、AGSIおよびAGSI+ストレージデータに関するAPI(Application Programming Interface)サービスを提供しています。APIドキュメントの作成は進行中であり、サービスの使用方法に関するサンプルやガイダンスも提供しており、APIキーを取得するための登録を行うと利用できます。以下は、過去半年のデータプロットです。

サンプルスクリプト/コードの入手先
スクリプトと画像は、https://github.com/maxkleiner/agsi-dataからダウンロードできます。
ダウンロードコードのサンプル
以下は、maXbox4統合用のWinAPIDownloadクラスからの抜粋です。
TWinApiDownload = class(TObject)
private
fEventWorkStart: TEventWorkStart;
fEventWork: TEventWork;
fEventWorkEnd: TEventWorkEnd;
fEventError: TEventError;
fURL: string;
fUserAgent: string;
fStop: Boolean;
fActive: Boolean;
fCachingEnabled: Boolean;
fProgressUpdateInterval: Cardinal;
function GetIsActive: Boolean;
public
constructor Create;
destructor Destroy; override;
function CheckURL(aURL: string): Integer;
function Download(Stream: TStream): Integer; overload;
function Download(var res: string): Integer; overload;
function ErrorCodeToMessageString(aErrorCode: Integer): string;
procedure Stop;
procedure Clear;
property UserAgent: string read fUserAgent write fUserAgent;
property URL: string read fURL write fURL;
property DownloadActive:Boolean read GetIsActive;
property CachingEnabled:Boolean read fCachingEnabled write fCachingEnabled;
property UpdateInterval:Cardinal read fProgressUpdateInterval
write fProgressUpdateInterval;
property OnWorkStart: TEventWorkStart read fEventWorkStart
write fEventWorkStart;
property OnWork: TEventWork read fEventWork write fEventWork;
property OnWorkEnd: TEventWorkEnd read fEventWorkEnd write fEventWorkEnd;
property OnError: TEventError read fEventError write fEventError;
end;
参考文献とリンク
- https://agsi.gie.eu/api
- https://www.gie.eu/transparency-platform/GIE_API_documentation_v006.pdf
- https://svn.code.sf.net/p/alcinoe/code/demos/ALWinInetHTTPClient/_source/Unit1.pas
- https://docwiki.embarcadero.com/Libraries/Sydney/en/System.Net.HttpClient.THTTPClient.Post
- ドキュメントとツール: https://maxbox4.wordpress.com (Script Ref: 1154_energy_api_agsi_plot14.txt)
Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.
Free Delphi Community Edition Free C++Builder Community Edition







