2019年2月21日木曜日

Install DCM4CHEE Archive light 5.x インストールメモ

Install DCM4CHEE Archive light 5.x インストールメモ

dcm4chee 5.x バージョンが出ていたのでインストールしてみました。
LDAPの設定が新たに必要になっています。
LDAPはモダリティの装置名などに使用するのでしょうか?「PS3.15 医療におけるデジタル画像と通信」にはなにやら書かれておりますが、とくに日常現場で使う必要はなさそうです。。

おおむね、マニュアル通りに設定をしていますが、LDAPが理解不足で。。。

対象OS: CentOS7 (CentOS-7-x86_64-Minimal-2009.iso)
----usbでインストール。その後、isoファイルをHDDに展開してローカルレポジトリとします。2024年以降も使いたい。。。。。

(以下 centosに入っているものをそのまま使用しています)

データベース: postgresql
LDAPサーバ: OpenLDAP
java: openjdk

01. OSの設定

centosにもpacsユーザを作成しておいた。

>useradd pacs
>passwd pacs
 適当なパスワード


フォルダは以下に展開

dcm4chee-arc-5.15.1-psql.zip >> /var/dcm4chee-arc
wildfly-12.0.0.Final.zip     >> /opt/wildfly


10. データベース

10.10. 設定

postgresql.conf,pg_hba.confは適宜に編集。

10.20. データベースとユーザの作成。

database: pacsdb
user: pacs


>su -l postgres
>createuser pacs
>psql -U postgres
postgres=#create database pacsdb owner pacs;
postgres=#\q


10.30. テーブルとインデックスの作成


>su -l pacs
psql pacsdb < /var/dcm4chee-arc/sql/create-psql.sql
psql pacsdb < /var/dcm4chee-arc/sql/create-fk-index.sql


20. LDAP Server

centos のものをそのまま使用します
centos7用のLDAPではslapd.confファイルを直接編集するのではなく、コマンドから設定します。

20.10. インストール


>yum -y install openldap openldap-clients openldap-servers


20.20. Berkeley DBのDB設定ファイルをコピー

>cp -p /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG


20.30. サービスの登録と起動


>systemctl enable slapd
>systemctl start slapd


20.40. 管理者パスワード


# slappasswd
  New passwrd:secret
  Re-enter new password: secret

  {SSHA}*****************************


20.50. ダイナミック設定  


>cd /var/dcm4chee-arc/ldap/slapd

>ldapadd -Y EXTERNAL -H ldapi:/// -f dicom.ldif
>ldapadd -Y EXTERNAL -H ldapi:/// -f dcm4che.ldif
>ldapadd -Y EXTERNAL -H ldapi:/// -f dcm4chee-archive.ldif
>ldapadd -Y EXTERNAL -H ldapi:/// -f dcm4chee-archive-ui.ldif


20.60. olcSuffixの書き換え(replace)

modify-baseDN.ldif を新規作成

>vi modify-baseDN.ldif
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=dcm4che,dc=org
-
replace: olcRootDN
olcRootDN: cn=admin,dc=dcm4che,dc=org
-

保存終了

実行します
>ldapmodify -Y EXTERNAL -H ldapi:/// -f modify-baseDN.ldif


確認します

ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'olcDatabase={2}hdb,cn=config'


20.70. パスワードの変更


>vi setup_pwd.ldif


dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}************************ #(20.40 で取得したもの)

dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}************************ #(20.40 で取得したもの)


実行

>ldapadd -Y EXTERNAL -H ldapi:// -f ./setup_pwd.ldif


確認

>ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'olcDatabase={2}hdb,cn=config'


20.80. 最上位要素とLDAP管理者アカウントのオブジェクトの作成



>vi slapd_setup_basic.ldif


dn: dc=dcm4che,dc=org
changetype: add
objectClass: top
objectClass: dcObject
objectClass: organization
o: dcm4che.org
dc: dcm4che

dn: cn=admin,dc=dcm4che,dc=org
changetype: add
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword: {SSHA}***************************

実行

>ldapmodify -x -D cn=admin,dc=dcm4che,dc=org -H ldapi:/// -f slapd_setup_basic.ldif -W
>secret


30. 設定をLDAPサーバにインポート


 Apache Directory Studio 2.0.0-M9 (http://directory.apache.org/studio/downloads.html)のダウンロード
 適当な場所に展開
 ApacheDirectoryStudio を実行

30.10. 設定

 Network Parameter:
    Hostname: localhost
    Port:     389
 Authentication Parameter:
    Bind DN or user: cn=admin,dc=dcm4che,dc=org
    Bind password:   secret
 Browser Options:                  #<=ない
    Base DN: dc=dcm4che,dc=org     #<=ない
 上記設定でログイン

30.20. インポート

 Connection > localhost(右クリック) > import
 /var/dcm4chee-arc/ldap以下の5つのファイルを import

init-baseDN.ldif      #<=もともと設定されているためエラー
init-config.ldif
default-config.ldif
default-ui-config.ldif
add-vendor-data.ldif

40. Wildflyの設定

40.10. インストール

ver 12.0
 /opt/wildfly へ解凍

40.20. dcm4cheeのconfiguration files のコピー



> cp -r /var/dcm4chee-arc/configuration/dcm4chee-arc /opt/wildfly/standalone/configuration


40.30. standalone-full.xml>dcm4chee-arc.xml



> cd /opt/wldfly/standalone/configuration/
> cp standalone-full.xml dcm4chee-arc.xml


40.40. ライブラリをJBossモジュールとしてインストール



>cd /opt/wildfly
>unzip /var/dcm4chee-arc/jboss-modules/dcm4che-jboss-modules-5.x.x.zip
>unzip /var/dcm4chee-arc/jboss-modules/jai_imageio-jboss-modules-1.2-pre-dr-b04.zip
>unzip /var/dcm4chee-arc/jboss-modules/querydsl-jboss-modules-4.2.1-noguava.zip
>unzip /var/dcm4chee-arc/jboss-modules/jclouds-jboss-modules-2.1.0-noguava.zip
>unzip /var/dcm4chee-arc/jboss-modules/ecs-object-client-jboss-modules-3.0.0.zip


40.50. jdbc ドライバー

 コアモジュールとして


>cd /opt/wildfly
>unzip /var/dcm4chee-arc/jboss-modules/jdbc-jboss-modules-1.0.0-psql.zip


40.60. postgresql-42.2.4.jar のダウンロードとコピー


>cp postgresql-42.2.5.jar /opt/wildfly/modules/org/postgresql/main/



40.70. module.xmlファイルの編集

resource-root path=を上記のダンロードしたファイル名にする


vi /opt/wildfly//modules/org/postgresql/main/module.xml


<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.postgresql">
    <resources>
        <resource-root path="postgresql-42.2.5.jar"/>
    </resources>

    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
    </dependencies>
</module>

40.80. スタンドアローンモードでWildFlyを起動



> /opt/wildfly/bin/standalone.sh -c dcm4chee-arc.xml



40.90. JBoss CLIを使用してJDBCドライバーをサーバー設定に追加

add-data-source-psql.cliの編集

  • >vi add-data-source-psql.cli


/subsystem=datasources/jdbc-driver=psql:add(driver-module-name=org.postgresql,driver-name=psql)
data-source add --name=pacsds --driver-name=psql --jndi-name=java:/PacsDS \
--connection-url=jdbc:postgresql://localhost:5432/pacsdb \
--user-name=pacs --password=pacsユーザのパスワード

実行

>/opt/wildfly/bin/jboss-cli.sh -c --file=/var/dcm4chee-arc/cli/add-data-source-psql.cli


確認

>/opt/wildfly/bin/jboss-cli.sh -c
[standalone@localhost:9990 /] ls subsystem
[standalone@localhost:9990 /] ls subsystem=datasources
[standalone@localhost:9990 /] ls subsystem=datasources/data-source=pacsds
[standalone@localhost:9990 /] ls subsystem=datasources/jdbc-driver=psql


40.100. JBoss CLIを使用してJMSキューを作成



>/opt/wildfly/bin/jboss-cli.sh -c --file=/var/dcm4chee-arc/cli/add-jms-queues.cli


40.110. JBoss CLIを使用してdcm4chee-arcをデプロイ(配備)


> /opt/wildfly/bin/jboss-cli.sh -c
[standalone@localhost:9990 /] deploy /var/dcm4chee-arc/deploy/dcm4chee-arc-ear-5.13.3-psql.ear


40.120. WildFlayのadmin ユーザーを作成


>/opt/wildfly/bin/add-user.sh
user-name: admin
password:  ******


50. ブラウザで参照

http://localhost:9990
http://localhost:8080/dcm4chee-arc/ui2.

60. sendscu

dcmtkよりstorescu
>storescu.exe -v -aet any -aec DCM4CHEE 192.168.0.* 11112 xray.dcm

(ちなみにフォルダごと再帰的に送信の場合は以下。極めて便利。dicom以外のファイルはスルーしてくれる)
>storescu.exe -v +r +sd -aet any -aec DCM4CHEE 192.168.0.* c:\temp\

70. 保存場所の変更

70.10. 保存場所

デフォルトは ${wildfly}/standalone/data/fs1 なので /data/にブラウザで変更
http://localhost:8080/dcm4chee-arc/ui2/

configration>Device>Dcm4Chee>Extension>ArchiveDrive>StorageDescriptor>StrageURI 
    file:///data/

70.20. 保存形式

保存形式はデフォルトでは送信日時だったのでstudydateに変更
>storageProperty
    pathFormat=00080020,date,yyyy}/{00080020,date,MM}/{00080020,date,dd}/{0020000D,hash}/{0020000E,hash}/{00080018,hash}

80. 自動実行

>useradd wildfly
>cd /opt
>chown -R wildfly:wildfly wildfly

>cd /etc
>mkdir wildfly
>cd wildfly
>cp /opt/wildfly/docs/contrib/scripts/systemd/wildfly.conf ./wildfly.conf
>vi wildfly.conf
    # The configuration you want to run
    WILDFLY_CONFIG=dcm4chee-arc.xml
    # The mode you want to run
    WILDFLY_MODE=standalone
    # The address to bind to
    WILDFLY_BIND=0.0.0.0

>cd /etc/systemd/system/
>cp -piv /opt/wildfly/docs/contrib/scripts/systemd/wildfly.service ./wildfly.service


>cd /opt/wildfly/bin/
>cp /opt/wildfly/docs/contrib/scripts/systemd/launch.sh ./launch.sh


/var/dcm4chee-arc にwildflyユーザの実行権限を再帰的に与えます。

>systemctl start wildfly
>systemctl enable wildfly






2017年2月19日日曜日

C#で直接印刷

C#で直接印刷

C#の直接印刷で手こずっていましたが、ghostscript.net で解決。

つかうもの。itextsharp, ghostscript.net そして、Adobe Illustrator cs2です。
itextsharp,ghostscript.net はそれぞれ NuGet にあるのでインストールしておきます。

1 Illustratorでテンプレートを作成


Adobe Illustratorで下地となるテンプレートを作成。
単位、座標をitextsharpと一致させます。
単位:ポイント
座標:左下 (「定規」を表示して左下に座標設定)
    Illustratorなのでかなり意匠の凝った印刷物が作成可。
    レイヤーでプログラムに使う座標なども作成しておくと便利。
最後に不必要なレイヤーを非表示にして「複製を保存」でpdfファイルを作成。

2 itextsharp


作成されたpdfファイルにコンテンツを追加していきます。
文字もグリッド用の線もすべて PdfContentByte で位置固定。

サンプル

using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

{

string filePaht="";
var template1 = new PdfReader(filePath);
var doc = new Document(PageSize.A4.Rotate());
FileStream fs = null;
fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();

//row.Count枚数の印刷物
foreach(DataRow row in table)

{
var page1 = writer.GetImportedPage(template1, 1);
doc.NewPage();
var pcd1 = writer.DirectContent;
pcd1.AddTemplate(page1, 0, 0);
AddContents(writer, row);
}
doc.Close();
fs.Close();
template1.Close();
}

//DataRowのコンテンツを追加します

private void AddContents(PdfWriter writer, DataRow row)
{
var cb = writer.DirectContent;
var bf = BaseFont.CreateFont(@"c:\windows\fonts\msgothic.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//
float x0=***f,y0=***f;
float w0=***f,h0=***f;
DrawTextAligned(cb, bf, 11f, row.Field<string>(1), new PointF(x0, y0), Element.ALIGN_LEFT);
//
DrawTextCell(cb, bf, 10f, r1[2].ToString(), new PointF(x0,y0), new SizeF(w0, h0), Element.ALIGN_LEFT);
//直線
DrawLine(cb, new PointF(x0, y0), new SizeF(w0, 0.0f), 0.5f, Color.Black.ToArgb());
}
//文字列一行
private static void DrawTextAligned(PdfContentByte cb, BaseFont bf, float fSize, string s, PointF xy, int alignment = Element.ALIGN_LEFT, int argb = -16777216)
{
if (s == "") return;
cb.BeginText();
BaseColor bc = new BaseColor(argb);
cb.SetColorFill(bc);
cb.SetFontAndSize(bf, fSize);
cb.ShowTextAligned(alignment, s, xy.X, xy.Y,0.0f);
cb.EndText();
}

//文字列 複数行
private static void DrawTextCell(PdfContentByte cb, BaseFont bf, float fontSize, string s, PointF xy, SizeF wh, int alignment = Element.ALIGN_LEFT,int arb=-16777216)
{
ColumnText col = new ColumnText(cb);
var font = new iTextSharp.text.Font(bf, fontSize);
Color color = Color.FromArgb(argb);
font.SetColor(color.R, color.G, color.B);
col.SetSimpleColumn(new Phrase(s, font), xy.X, xy.Y, xy.X + wh.Width, xy.Y + wh.Height, fontSize, alignment);
col.Go();
}
//直線
private static void DrawLine(PdfContentByte cb, PointF xy, SizeF wh, float lineWidth = 0.5f, int argb = -16777216)
{
BaseColor bc = new BaseColor(argb);
cb.MoveTo(xy.X, xy.Y);
cb.LineTo(xy.X + wh.Width, xy.Y+ wh.Height);
cb.SetLineWidth(lineWidth);
cb.SetColorStroke(bc);
cb.ClosePathStroke();
}
//塗りつぶし矩形
private static void DrawFillRect(PdfContentByte cb, PointF xy,SizeF wh, int argb)
{
BaseColor c=new BaseColor(argb);
cb.SetColorFill(c);
cb.Rectangle( xy.X, xy.Y,wh.Width,wh.Height);
cb.Fill();
}

ライン、文字列の関数はすべて ( x=左 y=下 w=幅, h=高さ )を変数に作成してありますが、これはIllastrator の「ウィンドウ> 変形」のXYWHと一致させるためです。Illastratorの「変形」の値を参照しながら位置を設定していきます。もし、Illastratorのオブジェクトの名前と位置をテキストにエクスポート出来ることができれば、もっと簡便に設定できるのですが。。

また、Illastrator「変形」の基準ポイント(9点)の 左、中央、右はitextsharpのElement.ALIGN_LEFT,Element.ALIGN_CENTER,Element.ALIGN_RIGHTに相当します。たとえば、Element.ALIGN_RIGHTだと xは右側が基準です。同様にElement.ALIGN_CENTERの場合は中央が基準です。

3 ghostscript.net


ghostscript.netで直接印刷します。
ghostscript.netにはプレビュー用のフォームのサンプルもあるのでビュアーも作成可能。 Acrobat Readerよりはずっと早い。

サンプルコード

using Ghostscript.NET;
using Ghostscript.NET.Viewer;
using Ghostscript.NET.Processor;

var pd = new System.Drawing.Printing.PrintDocument();
string printerName = pd.PrinterSettings.PrinterName;
string inputFile = ””;

using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dPrinted");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOSAFER");
switches.Add("-dNumCopies=1"); //部数
switches.Add("-sDEVICE=mswinpr2");
switches.Add("-sPAPERSIZE=a4");
//横指定A4
//switches.Add("-dDEVICEWIDTHPOINTS=842");
//switches.Add("-dDEVICEHEIGHTPOINTS=595");
//両面印刷
//switches.Add("-dDuplex");//TrueON,false=off
//switches.Add("-dTumble=true");//True=短辺綴じ false=長辺綴じ
switches.Add("-sOutputFile=%printer%" + printerName);
switches.Add("-f");
switches.Add(inputFile);
processor.StartProcessing(switches.ToArray(), null);
}

いままで印刷は、PrintDocumentクラスを使用したり、xpsを用いたりと四苦八苦していたのですが、Ghostscriptで簡単に行けそうです。あぁ無料。



2015年9月2日水曜日

GDCM memo

Move Scu

1) Study >> Series move
2) Study >> image move

1) Study からSeriesを抽出。series単位で move

var scp = new gdcm.ServiceClassUser();
ushort port = 11112;
ushort portScp = 104;
string aetcalled = "DCM4CHEE";
string aetcalling = "any";
string host = "192.168.0.100";
//
string patId = "12345";
//sendmove
var scu = new gdcm.ServiceClassUser();
//scu.SetHostname("192.168.17.13"); scu.SetAETitle("any");
scu.SetHostname(host);
scu.SetAETitle(aetcalling);//
scu.SetPort(port);
scu.SetTimeout(1d);
scu.SetCalledAETitle(aetcalled);
// InitializeConnection
if (!scu.InitializeConnection())
{ Console.WriteLine("Err :Init"); return; }
var generator = new PresentationContextGenerator();
var retDatasets = new DataSetArrayType();
// Find SCU
var theTagPair = new gdcm.KeyValuePairArrayType();
theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), "*"));    //StudyInstanceUID
var findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eStudy, theTagPair);
if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
string studyInstanceUid = string.Empty;
string seriesInstanceUid = string.Empty;
           
if (!scu.StartAssociation())
{ Console.WriteLine("Err :StartAssociation"); return; }
if (scu.SendFind(findquery, retDatasets))
{
    if (retDatasets.Count > 0)
    {
        foreach (gdcm.DataSet d in retDatasets)
            Console.WriteLine("StudyInstanceUID :" + d.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).toString());
        // Find Last StudyInstancUID to SeriesInstanceUID
        theTagPair = new KeyValuePairArrayType();
        studyInstanceUid=retDatasets[retDatasets.Count - 1].GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString();
        Console.WriteLine(studyInstanceUid);
        theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), studyInstanceUid));
        theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), "*"));
        findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eSeries, theTagPair);
        if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
        { Console.WriteLine("Err :VerificationSOPClass"); return; }
        scu.SetPresentationContexts(generator.GetPresentationContexts());
        retDatasets=new DataSetArrayType();
        if (scu.SendFind(findquery, retDatasets))
        {
            Console.WriteLine(retDatasets.Count);
            if (retDatasets.Count > 0)
            {
                foreach (gdcm.DataSet d in retDatasets)
                    Console.WriteLine("SeriesInstanceUID :" + d.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).toString());
            }
        }
    }
}
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
//
if (retDatasets.Count == 0)
    return;
var moveds = new gdcm.DataSet();
// Last SeriesInstanceUID
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000D)));
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000E)));
//
var movequery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, moveds, true);
//
if (!generator.GenerateFromUID(movequery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
scu.SetPortSCP(portScp);    //PortSCU
if (!scu.StartAssociation())
{ Console.WriteLine("Err :scu StartAssociation"); return; }
var data = new gdcm.DataSetArrayType();
if (!scu.SendMove(movequery, data))
    Console.WriteLine("Err : SendMove");
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
foreach (gdcm.DataSet d in data)
{
    // represent Photmetric Interpretation
    if(d.FindDataElement(new gdcm.Tag(0x0028,0004)))
        Console.WriteLine(d.GetDataElement(new gdcm.Tag(0x0028,0004)).GetValue().toString());

}
Console.WriteLine("...End");

2)  Study から imageごとに move

var scp = new gdcm.ServiceClassUser();
ushort port = 11112;
ushort portScp = 104;
string aetcalled = "DCM4CHEE";
string aetcalling = "any";
string host = "192.168.0.100";
//
string patId = "12345";
//sendmove
var scu = new gdcm.ServiceClassUser();
//scu.SetHostname("192.168.17.13"); scu.SetAETitle("any");
scu.SetHostname(host);
scu.SetAETitle(aetcalling);//
scu.SetPort(port);
scu.SetTimeout(1d);
scu.SetCalledAETitle(aetcalled);
// InitializeConnection
if (!scu.InitializeConnection())
{ Console.WriteLine("Err :Init"); return; }
var generator = new PresentationContextGenerator();
var retDatasets = new DataSetArrayType();
// Find SCU
var theTagPair = new gdcm.KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0018), "*"));//SOPInstanceUID
var findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, theTagPair);
if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
if (!scu.StartAssociation())
{ Console.WriteLine("Err :StartAssociation"); return; }
if (!scu.SendFind(findquery, retDatasets))
{ Console.WriteLine("Err :SendFind"); return; }
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
//
if (retDatasets.Count == 0)
    return;

var moveds = new gdcm.DataSet();
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0010, 0x0020)));
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000D)));
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000E)));
//
var movequery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, moveds, true);
//
if (!generator.GenerateFromUID(movequery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
scu.SetPortSCP(portScp);

if (!scu.StartAssociation())
{ Console.WriteLine("Err :scu StartAssociation"); return; }
            
for (int i = 0; i < retDatasets.Count; i++)
{
    var queryds = movequery.GetQueryDataSet();

    var instanceuid = retDatasets[i].GetDataElement(new gdcm.Tag(0x0008, 0x0018));
    Console.WriteLine(instanceuid.toString());
    queryds.Replace(instanceuid);
    var data = new gdcm.DataSetArrayType();
    if (!scu.SendMove(movequery, data))
    { Console.WriteLine("Err : SendMove"); break; }
    var d = data[0];
    // represent Photmetric Interpretation
    if (d.FindDataElement(new gdcm.Tag(0x0028, 0004)))
        Console.WriteLine(d.GetDataElement(new gdcm.Tag(0x0028, 0004)).GetValue().toString());


}
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
Console.WriteLine("End");

2015年8月28日金曜日

GDCM memo

Find Scu

PatID>>StudyInstansUID>>SeriesInstanceUID>>SOPInstanceUID
患者番号からSOPInstanceUIDを抽出

ushort port = 11112;
string aetcalled = "DCM4CHEE";
string aetcalling = "any";
string host = "192.168.0.1";
//Patient Number
string patId="123";
//Study Level
gdcm.PresentationContextGenerator generator = new PresentationContextGenerator();
gdcm.KeyValuePairArrayType theTagPair = new KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0010), "*"));    //Name
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0030), "*"));    //Birthday
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0040), "*"));    //Sex
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), "*"));    //StudyInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0050), "*"));    //AccessionNumber
var query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.ePatientRootType,
    gdcm.EQueryLevel.eStudy, theTagPair);
var ret = new DataSetArrayType();
bool b = gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
List studyInsUidList = new List();
for (int i = 0; i < ret.Count; i++)
{
    var ds = ret[i];
    Console.WriteLine("StudyInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString());
    studyInsUidList.Add(ds.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString());
}
//Series Level
string studyInsUid = studyInsUidList[0].Trim(); //Select First Series                 
theTagPair = new KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), studyInsUid));    //StudyInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), "*"));            //SeriesInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0060), "*"));            //Modality
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x0011), "*"));            //SeriesNumber
query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType,
    gdcm.EQueryLevel.eSeries, theTagPair);
ret = new DataSetArrayType();
gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
List seriesInsUidList = new List();
for (int i = 0; i < ret.Count; i++)
{
    var ds = ret[i];
    Console.WriteLine("SeriesInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0020, 0x000E)).GetValue().toString());
    seriesInsUidList.Add(ds.GetDataElement(new gdcm.Tag(0x0020, 0x000E)).GetValue().toString());
}
//Image Level
string seriesInsUid = seriesInsUidList[0].Trim(); //Select First Series                 
theTagPair = new KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), seriesInsUid));   //SeriesInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x0013), "*"));            //InstanceNumber
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0018), "*"));            //SOPInstanceUID
query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType,
    gdcm.EQueryLevel.eImage, theTagPair);
ret = new DataSetArrayType();
gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);

for (int i = 0; i < ret.Count; i++)
{
    var ds = ret[i];
    Console.WriteLine("SopInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0008, 0x0018)).GetValue().toString());
}