# ClinicalTrialIdentificationWorkflow.cs

This is a C# example on how to use gdcm::Anonymizer

    /*=========================================================================

      Program: GDCM (Grassroots DICOM). A DICOM library
      Module:  $URL$

      Copyright (c) 2006-2009 Mathieu Malaterre
      All rights reserved.
      See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.

         This software is distributed WITHOUT ANY WARRANTY; without even
         the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
         PURPOSE.  See the above copyright notice for more information.

    =========================================================================*/
    /*
    PS 3.17 - 2008
    Annex H. Clinical Trial Identification Workflow Examples
    (Informative)
    This Annex was formerly located in Annex O of PS 3.3 in the 2003 and earlier revisions of the standard.
    The Clinical Trial Identification modules are optional. As such, there are several points in the workflow of
    clinical trial data at which the Clinical Trial Identification attributes may be added to the data. At the
    Clinical Trial Site, the attributes may be added at the scanner, a PACS system, a site workstation, or a
    workstation provided to the site by a Clinical Trial Coordinating Center. If not added at the site, the
    Clinical Trial Identification attributes may be added to the data after receipt by the Clinical Trial
    Coordinating Center. The addition of clinical trial attributes does not itself require changes to the SOP
    Instance UID. However, the clinical trial protocol or the process of de-identification may require such a
    change.
    */

    /*
     * Usage:
     * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin
     * $ mono bin/ClinicalTrialIdentificationWorkflow.exe input_dir output_dir
     */
    using System;
    using gdcm;

    public class MyWatcher : SimpleSubjectWatcher
    {
      public MyWatcher(Subject s):base(s,"Override String"){}
      protected override void StartFilter() {
        System.Console.WriteLine( "This is my start" );
      }
      protected override void EndFilter(){
        System.Console.WriteLine( "This is my end" );
      }
      protected override void ShowProgress(){
        System.Console.WriteLine( "This is my progress" );
      }
      protected override void ShowIteration(){
        System.Console.WriteLine( "This is my iteration" );
      }
      protected override void ShowAnonymization(Subject caller, Event evt){
    /*
     * A couple of explanation are necessary here to understand how SWIG work
     *  http://www.swig.org/Doc1.3/Java.html#adding_downcasts
     *
     *  System.Console.WriteLine( "This is my Anonymization. Type: " + evt.GetEventName() );
     *  System.Type type = evt.GetType();
     *  System.Console.WriteLine( "This is my Anonymization. System.Type: " + type.ToString() );
     *  System.Console.WriteLine( "This is my Anonymization. CheckEvent: " + ae.CheckEvent( evt ) );
     *  System.Console.WriteLine( "This is my Anonymization. Processing Tag #" + ae.GetTag().toString() );
     */
        AnonymizeEvent ae = AnonymizeEvent.Cast(evt);
        if( ae != null )
          {
          Tag t = ae.GetTag();
          System.Console.WriteLine( "This is my Anonymization. Processing Tag #" + t.toString() );
          }
        else
          {
          System.Console.WriteLine( "This is my Anonymization. Unhandled Event type: " + evt.GetEventName() );
          }
      }
      protected override void ShowAbort(){
        System.Console.WriteLine( "This is my abort" );
      }
    }

    public class ClinicalTrialIdentificationWorkflow
    {
      public static bool ProcessOneFile( gdcm.Anonymizer ano , string filename, string outfilename )
        {
        Reader reader = new Reader();
        reader.SetFileName( filename );
        bool ret = reader.Read();
        if( !ret )
          {
          return false;
          }
        // Pass in the file:
        ano.SetFile( reader.GetFile() );

        // First step, let's protect all Patient information as per
        // PS 3.15 / E.1 / Basic Application Level Confidentiality Profile
        if( !ano.BasicApplicationLevelConfidentialityProfile() )
          {
          return false;
          }

        // Now let's pass in all Clinical Trial fields
        // PS 3.3 - 2008 / C.7.1.3 Clinical Trial Subject Module
        /*
        Clinical Trial Sponsor Name (0012,0010) 1 The name of the clinical trial sponsor. See C.7.1.3.1.1.
        Clinical Trial Protocol ID (0012,0020) 1 Identifier for the noted protocol. See C.7.1.3.1.2.
        Clinical Trial Protocol Name (0012,0021) 2 The name of the clinical trial protocol. See C.7.1.3.1.3.
        Clinical Trial Site ID (0012,0030) 2 The identifier of the site responsible for submitting clinical trial data. See C.7.1.3.1.4.
        Clinical Trial Site Name (0012,0031) 2 Name of the site responsible for submitting clinical trial data. See C.7.1.3.1.5
        Clinical Trial Subject ID (0012,0040) 1C The assigned identifier for the clinical trial subject. See C.7.1.3.1.6. Shall be present if Clinical Trial Subject Reading ID (0012,0042) is absent. May be present otherwise.
        Clinical Trial Subject Reading ID (0012,0042) 1C Identifies the subject for blinded evaluations. Shall be present if Clinical Trial Subject ID (0012,0040) is absent.  May be present otherwise. See C.7.1.3.1.7.
         */
        ano.Replace( new gdcm.Tag(0x0012,0x0010), "MySponsorName");
        ano.Replace( new gdcm.Tag(0x0012,0x0020), "MyProtocolID");
        ano.Replace( new gdcm.Tag(0x0012,0x0021), "MyProtocolName");
        ano.Replace( new gdcm.Tag(0x0012,0x0030), "MySiteId");
        ano.Replace( new gdcm.Tag(0x0012,0x0031), "MySiteName");
        ano.Replace( new gdcm.Tag(0x0012,0x0040), "MySponsorId");
        ano.Replace( new gdcm.Tag(0x0012,0x0050), "MyTPId");
        ano.Replace( new gdcm.Tag(0x0012,0x0051), "MyTPDescription");

        // The following two are not required as they are guaranteed to be filled in by the
        // Basic Application Level Confidentiality Profile. Only override if you understand what
        // you are doing
        //ano.Replace( new gdcm.Tag(0x0012,0x0062), "YES");
        //ano.Replace( new gdcm.Tag(0x0012,0x0063), "My Super Duper Anonymization Overload");

        // We might be generating a subdirectory. Let's make sure the subdir exist:
        gdcm.Filename fn = new gdcm.Filename( outfilename );
        string subdir = fn.GetPath();
        if( !gdcm.PosixEmulation.MakeDirectory( subdir ) )
          {
          return false;
          }

        gdcm.FileMetaInformation fmi = ano.GetFile().GetHeader();
        // The following three lines make sure to regenerate any value:
        fmi.Remove( new gdcm.Tag(0x0002,0x0012) );
        fmi.Remove( new gdcm.Tag(0x0002,0x0013) );
        fmi.Remove( new gdcm.Tag(0x0002,0x0016) );

        Writer writer = new Writer();
        writer.SetFileName( outfilename );
        writer.SetFile( ano.GetFile() );
        ret = writer.Write();
        if( !ret )
          {
          return false;
          }

        return true;
        }

      public static int Main(string[] args)
        {
        gdcm.FileMetaInformation.SetSourceApplicationEntityTitle( "My ClinicalTrial App" );

        // http://www.oid-info.com/get/1.3.6.1.4.17434
        string THERALYS_ORG_ROOT = "1.3.6.1.4.17434";
        gdcm.UIDGenerator.SetRoot( THERALYS_ORG_ROOT );
        System.Console.WriteLine( "Root dir is now: " + gdcm.UIDGenerator.GetRoot() );

        gdcm.Global global = gdcm.Global.GetInstance();
        if( !global.LoadResourcesFiles() )
          {
          System.Console.WriteLine( "Could not LoadResourcesFiles" );
          return 1;
          }

        string dir1 = args[0];
        string dir2 = args[1];

        // Check input is valid:
        if( !gdcm.PosixEmulation.FileIsDirectory(dir1) )
          {
          System.Console.WriteLine( "Input directory: " + dir1 + " does not exist. Sorry" );
          return 1;
          }
        if( !gdcm.PosixEmulation.FileIsDirectory(dir2) )
          {
          System.Console.WriteLine( "Output directory: " + dir2 + " does not exist. Sorry" );
          return 1;
          }

        Directory d = new Directory();
        uint nfiles = d.Load( dir1, true );
        if(nfiles == 0) return 1;

        string certpath = gdcm.Filename.Join(gdcm.Testing.GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" );
        gdcm.CryptographicMessageSyntax cms = new gdcm.CryptographicMessageSyntax();
        if( !cms.ParseCertificateFile( certpath ) )
          {
          return 1;
          }

        //Anonymizer ano = new Anonymizer();
        SmartPtrAno sano = Anonymizer.New();
        Anonymizer ano = sano.__ref__();

        //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(ano, "Anonymizer");
        MyWatcher watcher = new MyWatcher(ano);

        ano.SetCryptographicMessageSyntax( cms );

        // Process all filenames:
        FilenamesType filenames = d.GetFilenames();
        for( uint i = 0; i < nfiles; ++i )
          {
          string filename = filenames[ (int)i ];
          string outfilename = filename.Replace( dir1, dir2 );
          System.Console.WriteLine( "Filename: " + filename );
          System.Console.WriteLine( "Out Filename: " + outfilename );
          if( !ProcessOneFile( ano , filename, outfilename ) )
            {
            System.Console.WriteLine( "Could not process filename: " + filename );
            return 1;
            }
          }

        return 0;
        }
    }