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 で位置固定。

サンプル

  1. using System.IO;
  2. using iTextSharp.text;
  3. using iTextSharp.text.pdf;
  4.  
  5. {
  6.  
  7. string filePaht="";
  8. var template1 = new PdfReader(filePath);
  9. var doc = new Document(PageSize.A4.Rotate());
  10. FileStream fs = null;
  11. fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
  12. var writer = PdfWriter.GetInstance(doc, fs);
  13. doc.Open();
  14.  
  15. //row.Count枚数の印刷物
  16. foreach(DataRow row in table)
  17.  
  18. {
  19. var page1 = writer.GetImportedPage(template1, 1);
  20. doc.NewPage();
  21. var pcd1 = writer.DirectContent;
  22. pcd1.AddTemplate(page1, 0, 0);
  23. AddContents(writer, row);
  24. }
  25. doc.Close();
  26. fs.Close();
  27. template1.Close();
  28. }
  29.  
  30. //DataRowのコンテンツを追加します
  31.  
  32. private void AddContents(PdfWriter writer, DataRow row)
  33. {
  34. var cb = writer.DirectContent;
  35. var bf = BaseFont.CreateFont(@"c:\windows\fonts\msgothic.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
  36. //
  37. float x0=***f,y0=***f;
  38. float w0=***f,h0=***f;
  39. DrawTextAligned(cb, bf, 11f, row.Field<string>(1), new PointF(x0, y0), Element.ALIGN_LEFT);
  40. //
  41. DrawTextCell(cb, bf, 10f, r1[2].ToString(), new PointF(x0,y0), new SizeF(w0, h0), Element.ALIGN_LEFT);
  42. //直線
  43. DrawLine(cb, new PointF(x0, y0), new SizeF(w0, 0.0f), 0.5f, Color.Black.ToArgb());
  44. }
  45. //文字列一行
  46. private static void DrawTextAligned(PdfContentByte cb, BaseFont bf, float fSize, string s, PointF xy, int alignment = Element.ALIGN_LEFT, int argb = -16777216)
  47. {
  48. if (s == "") return;
  49. cb.BeginText();
  50. BaseColor bc = new BaseColor(argb);
  51. cb.SetColorFill(bc);
  52. cb.SetFontAndSize(bf, fSize);
  53. cb.ShowTextAligned(alignment, s, xy.X, xy.Y,0.0f);
  54. cb.EndText();
  55. }
  56.  
  57. //文字列 複数行
  58. private static void DrawTextCell(PdfContentByte cb, BaseFont bf, float fontSize, string s, PointF xy, SizeF wh, int alignment = Element.ALIGN_LEFT,int arb=-16777216)
  59. {
  60. ColumnText col = new ColumnText(cb);
  61. var font = new iTextSharp.text.Font(bf, fontSize);
  62. Color color = Color.FromArgb(argb);
  63. font.SetColor(color.R, color.G, color.B);
  64. col.SetSimpleColumn(new Phrase(s, font), xy.X, xy.Y, xy.X + wh.Width, xy.Y + wh.Height, fontSize, alignment);
  65. col.Go();
  66. }
  67. //直線
  68. private static void DrawLine(PdfContentByte cb, PointF xy, SizeF wh, float lineWidth = 0.5f, int argb = -16777216)
  69. {
  70. BaseColor bc = new BaseColor(argb);
  71. cb.MoveTo(xy.X, xy.Y);
  72. cb.LineTo(xy.X + wh.Width, xy.Y+ wh.Height);
  73. cb.SetLineWidth(lineWidth);
  74. cb.SetColorStroke(bc);
  75. cb.ClosePathStroke();
  76. }
  77. //塗りつぶし矩形
  78. private static void DrawFillRect(PdfContentByte cb, PointF xy,SizeF wh, int argb)
  79. {
  80. BaseColor c=new BaseColor(argb);
  81. cb.SetColorFill(c);
  82. cb.Rectangle( xy.X, xy.Y,wh.Width,wh.Height);
  83. cb.Fill();
  84. }

ライン、文字列の関数はすべて ( 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よりはずっと早い。

サンプルコード

  1. using Ghostscript.NET;
  2. using Ghostscript.NET.Viewer;
  3. using Ghostscript.NET.Processor;
  4.  
  5. var pd = new System.Drawing.Printing.PrintDocument();
  6. string printerName = pd.PrinterSettings.PrinterName;
  7. string inputFile = ””;
  8.  
  9. using (GhostscriptProcessor processor = new GhostscriptProcessor())
  10. {
  11. List<string> switches = new List<string>();
  12. switches.Add("-empty");
  13. switches.Add("-dPrinted");
  14. switches.Add("-dBATCH");
  15. switches.Add("-dNOPAUSE");
  16. switches.Add("-dNOSAFER");
  17. switches.Add("-dNumCopies=1"); //部数
  18. switches.Add("-sDEVICE=mswinpr2");
  19. switches.Add("-sPAPERSIZE=a4");
  20. //横指定A4
  21. //switches.Add("-dDEVICEWIDTHPOINTS=842");
  22. //switches.Add("-dDEVICEHEIGHTPOINTS=595");
  23. //両面印刷
  24. //switches.Add("-dDuplex");//TrueON,false=off
  25. //switches.Add("-dTumble=true");//True=短辺綴じ false=長辺綴じ
  26. switches.Add("-sOutputFile=%printer%" + printerName);
  27. switches.Add("-f");
  28. switches.Add(inputFile);
  29. processor.StartProcessing(switches.ToArray(), null);
  30. }

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



2015年9月2日水曜日

GDCM memo

Move Scu

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

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

  1. var scp = new gdcm.ServiceClassUser();
  2. ushort port = 11112;
  3. ushort portScp = 104;
  4. string aetcalled = "DCM4CHEE";
  5. string aetcalling = "any";
  6. string host = "192.168.0.100";
  7. //
  8. string patId = "12345";
  9. //sendmove
  10. var scu = new gdcm.ServiceClassUser();
  11. //scu.SetHostname("192.168.17.13"); scu.SetAETitle("any");
  12. scu.SetHostname(host);
  13. scu.SetAETitle(aetcalling);//
  14. scu.SetPort(port);
  15. scu.SetTimeout(1d);
  16. scu.SetCalledAETitle(aetcalled);
  17. // InitializeConnection
  18. if (!scu.InitializeConnection())
  19. { Console.WriteLine("Err :Init"); return; }
  20. var generator = new PresentationContextGenerator();
  21. var retDatasets = new DataSetArrayType();
  22. // Find SCU
  23. var theTagPair = new gdcm.KeyValuePairArrayType();
  24. theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
  25. theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), "*")); //StudyInstanceUID
  26. var findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eStudy, theTagPair);
  27. if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
  28. { Console.WriteLine("Err :VerificationSOPClass"); return; }
  29. scu.SetPresentationContexts(generator.GetPresentationContexts());
  30. string studyInstanceUid = string.Empty;
  31. string seriesInstanceUid = string.Empty;
  32. if (!scu.StartAssociation())
  33. { Console.WriteLine("Err :StartAssociation"); return; }
  34. if (scu.SendFind(findquery, retDatasets))
  35. {
  36. if (retDatasets.Count > 0)
  37. {
  38. foreach (gdcm.DataSet d in retDatasets)
  39. Console.WriteLine("StudyInstanceUID :" + d.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).toString());
  40. // Find Last StudyInstancUID to SeriesInstanceUID
  41. theTagPair = new KeyValuePairArrayType();
  42. studyInstanceUid=retDatasets[retDatasets.Count - 1].GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString();
  43. Console.WriteLine(studyInstanceUid);
  44. theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), studyInstanceUid));
  45. theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), "*"));
  46. findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eSeries, theTagPair);
  47. if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
  48. { Console.WriteLine("Err :VerificationSOPClass"); return; }
  49. scu.SetPresentationContexts(generator.GetPresentationContexts());
  50. retDatasets=new DataSetArrayType();
  51. if (scu.SendFind(findquery, retDatasets))
  52. {
  53. Console.WriteLine(retDatasets.Count);
  54. if (retDatasets.Count > 0)
  55. {
  56. foreach (gdcm.DataSet d in retDatasets)
  57. Console.WriteLine("SeriesInstanceUID :" + d.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).toString());
  58. }
  59. }
  60. }
  61. }
  62. if (!scu.StopAssociation())
  63. { Console.WriteLine("Err :scu StopAssociation"); return; }
  64. //
  65. if (retDatasets.Count == 0)
  66. return;
  67. var moveds = new gdcm.DataSet();
  68. // Last SeriesInstanceUID
  69. moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000D)));
  70. moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000E)));
  71. //
  72. var movequery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, moveds, true);
  73. //
  74. if (!generator.GenerateFromUID(movequery.GetAbstractSyntaxUID()))
  75. { Console.WriteLine("Err :VerificationSOPClass"); return; }
  76. scu.SetPresentationContexts(generator.GetPresentationContexts());
  77. scu.SetPortSCP(portScp); //PortSCU
  78. if (!scu.StartAssociation())
  79. { Console.WriteLine("Err :scu StartAssociation"); return; }
  80. var data = new gdcm.DataSetArrayType();
  81. if (!scu.SendMove(movequery, data))
  82. Console.WriteLine("Err : SendMove");
  83. if (!scu.StopAssociation())
  84. { Console.WriteLine("Err :scu StopAssociation"); return; }
  85. foreach (gdcm.DataSet d in data)
  86. {
  87. // represent Photmetric Interpretation
  88. if(d.FindDataElement(new gdcm.Tag(0x0028,0004)))
  89. Console.WriteLine(d.GetDataElement(new gdcm.Tag(0x0028,0004)).GetValue().toString());
  90.  
  91. }
  92. Console.WriteLine("...End");

2)  Study から imageごとに move

  1. var scp = new gdcm.ServiceClassUser();
  2. ushort port = 11112;
  3. ushort portScp = 104;
  4. string aetcalled = "DCM4CHEE";
  5. string aetcalling = "any";
  6. string host = "192.168.0.100";
  7. //
  8. string patId = "12345";
  9. //sendmove
  10. var scu = new gdcm.ServiceClassUser();
  11. //scu.SetHostname("192.168.17.13"); scu.SetAETitle("any");
  12. scu.SetHostname(host);
  13. scu.SetAETitle(aetcalling);//
  14. scu.SetPort(port);
  15. scu.SetTimeout(1d);
  16. scu.SetCalledAETitle(aetcalled);
  17. // InitializeConnection
  18. if (!scu.InitializeConnection())
  19. { Console.WriteLine("Err :Init"); return; }
  20. var generator = new PresentationContextGenerator();
  21. var retDatasets = new DataSetArrayType();
  22. // Find SCU
  23. var theTagPair = new gdcm.KeyValuePairArrayType();
  24. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
  25. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0018), "*"));//SOPInstanceUID
  26. var findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, theTagPair);
  27. if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
  28. { Console.WriteLine("Err :VerificationSOPClass"); return; }
  29. scu.SetPresentationContexts(generator.GetPresentationContexts());
  30. if (!scu.StartAssociation())
  31. { Console.WriteLine("Err :StartAssociation"); return; }
  32. if (!scu.SendFind(findquery, retDatasets))
  33. { Console.WriteLine("Err :SendFind"); return; }
  34. if (!scu.StopAssociation())
  35. { Console.WriteLine("Err :scu StopAssociation"); return; }
  36. //
  37. if (retDatasets.Count == 0)
  38. return;
  39.  
  40. var moveds = new gdcm.DataSet();
  41. moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0010, 0x0020)));
  42. moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000D)));
  43. moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000E)));
  44. //
  45. var movequery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, moveds, true);
  46. //
  47. if (!generator.GenerateFromUID(movequery.GetAbstractSyntaxUID()))
  48. { Console.WriteLine("Err :VerificationSOPClass"); return; }
  49. scu.SetPresentationContexts(generator.GetPresentationContexts());
  50. scu.SetPortSCP(portScp);
  51.  
  52. if (!scu.StartAssociation())
  53. { Console.WriteLine("Err :scu StartAssociation"); return; }
  54. for (int i = 0; i < retDatasets.Count; i++)
  55. {
  56. var queryds = movequery.GetQueryDataSet();
  57.  
  58. var instanceuid = retDatasets[i].GetDataElement(new gdcm.Tag(0x0008, 0x0018));
  59. Console.WriteLine(instanceuid.toString());
  60. queryds.Replace(instanceuid);
  61. var data = new gdcm.DataSetArrayType();
  62. if (!scu.SendMove(movequery, data))
  63. { Console.WriteLine("Err : SendMove"); break; }
  64. var d = data[0];
  65. // represent Photmetric Interpretation
  66. if (d.FindDataElement(new gdcm.Tag(0x0028, 0004)))
  67. Console.WriteLine(d.GetDataElement(new gdcm.Tag(0x0028, 0004)).GetValue().toString());
  68.  
  69.  
  70. }
  71. if (!scu.StopAssociation())
  72. { Console.WriteLine("Err :scu StopAssociation"); return; }
  73. Console.WriteLine("End");

2015年8月28日金曜日

GDCM memo

Find Scu

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

  1. ushort port = 11112;
  2. string aetcalled = "DCM4CHEE";
  3. string aetcalling = "any";
  4. string host = "192.168.0.1";
  5. //Patient Number
  6. string patId="123";
  7. //Study Level
  8. gdcm.PresentationContextGenerator generator = new PresentationContextGenerator();
  9. gdcm.KeyValuePairArrayType theTagPair = new KeyValuePairArrayType();
  10. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
  11. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0010), "*")); //Name
  12. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0030), "*")); //Birthday
  13. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0040), "*")); //Sex
  14. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), "*")); //StudyInstanceUID
  15. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0050), "*")); //AccessionNumber
  16. var query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.ePatientRootType,
  17. gdcm.EQueryLevel.eStudy, theTagPair);
  18. var ret = new DataSetArrayType();
  19. bool b = gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
  20. List studyInsUidList = new List();
  21. for (int i = 0; i < ret.Count; i++)
  22. {
  23. var ds = ret[i];
  24. Console.WriteLine("StudyInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString());
  25. studyInsUidList.Add(ds.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString());
  26. }
  27. //Series Level
  28. string studyInsUid = studyInsUidList[0].Trim(); //Select First Series
  29. theTagPair = new KeyValuePairArrayType();
  30. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), studyInsUid)); //StudyInstanceUID
  31. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), "*")); //SeriesInstanceUID
  32. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0060), "*")); //Modality
  33. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x0011), "*")); //SeriesNumber
  34. query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType,
  35. gdcm.EQueryLevel.eSeries, theTagPair);
  36. ret = new DataSetArrayType();
  37. gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
  38. List seriesInsUidList = new List();
  39. for (int i = 0; i < ret.Count; i++)
  40. {
  41. var ds = ret[i];
  42. Console.WriteLine("SeriesInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0020, 0x000E)).GetValue().toString());
  43. seriesInsUidList.Add(ds.GetDataElement(new gdcm.Tag(0x0020, 0x000E)).GetValue().toString());
  44. }
  45. //Image Level
  46. string seriesInsUid = seriesInsUidList[0].Trim(); //Select First Series
  47. theTagPair = new KeyValuePairArrayType();
  48. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), seriesInsUid)); //SeriesInstanceUID
  49. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x0013), "*")); //InstanceNumber
  50. theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0018), "*")); //SOPInstanceUID
  51. query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType,
  52. gdcm.EQueryLevel.eImage, theTagPair);
  53. ret = new DataSetArrayType();
  54. gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
  55. for (int i = 0; i < ret.Count; i++)
  56. {
  57. var ds = ret[i];
  58. Console.WriteLine("SopInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0008, 0x0018)).GetValue().toString());
  59. }