You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ctakes.apache.org by se...@apache.org on 2023/02/03 13:54:08 UTC

[ctakes] branch main updated: Refactored PBJ, moved python from src/main to src/user, some renaming Added pbj cnlpt negation example to ctakes-examples, need to add more of the cnlpt examples Added PythonRunner extracted AbstractCommandRunner from PythonRunner and CommandRunner moved configparam Wait to PausableAE Added PbjPipper and the cli --pipPbj improved FinishedLogger's understanding of _init added better support for virtual environments Everything else is Suppression or improvement to get rid of compile time warnings

This is an automated email from the ASF dual-hosted git repository.

seanfinan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ctakes.git


The following commit(s) were added to refs/heads/main by this push:
     new 84ff806  Refactored PBJ, moved python from src/main to src/user, some renaming Added pbj cnlpt negation example to ctakes-examples, need to add more of the cnlpt examples Added PythonRunner extracted AbstractCommandRunner from PythonRunner and CommandRunner moved configparam Wait to PausableAE Added PbjPipper and the cli --pipPbj improved FinishedLogger's understanding of _init added better support for virtual environments  Everything else is Suppression or improvement to get rid [...]
84ff806 is described below

commit 84ff8060e43ce9fa161af4f432d4aa524910c835
Author: Sean Finan <se...@childrens.harvard.edu>
AuthorDate: Fri Feb 3 08:53:55 2023 -0500

    Refactored PBJ, moved python from src/main to src/user, some renaming
    Added pbj cnlpt negation example to ctakes-examples, need to add more of the cnlpt examples
    Added PythonRunner
    extracted AbstractCommandRunner from PythonRunner and CommandRunner
    moved configparam Wait to PausableAE
    Added PbjPipper and the cli --pipPbj
    improved FinishedLogger's understanding of _init
    added better support for virtual environments
     Everything else is Suppression or improvement to get rid of compile time warnings
---
 .../assertion/cr/XmiCollectionReaderCtakes.java    |   3 +
 .../ctakes/assertion/medfacts/CasIndexer.java      |   3 +-
 .../cleartk/windowed/context/FollowingContext.java |   1 +
 .../runtime/BagOfAnnotationsGenerator.java         |   3 +-
 .../ctakes/core/ae/AbstractCommandRunner.java      | 128 ++++++++++++++++
 .../org/apache/ctakes/core/ae/CommandRunner.java   | 104 +++----------
 .../org/apache/ctakes/core/ae/CtakesRunner.java    |  28 ++--
 .../org/apache/ctakes/core/ae/PythonRunner.java    | 164 +++++++++++++++++++++
 .../apache/ctakes/core/ae/inert/PausableAE.java    |  16 +-
 .../ctakes/core/cr/JdbcCollectionReader.java       |   1 +
 .../ctakes/core/cr/jdbc/JdbcNotesReader.java       |   1 +
 .../ctakes/core/pipeline/CliOptionalsHandler.java  |   2 +
 .../ctakes/core/pipeline/PipeBitLocator.java       |   1 +
 .../ctakes/core/pipeline/StandardCliOptions.java   |   7 +
 .../org/apache/ctakes/core/util/ListIterable.java  |   3 +-
 .../ctakes/core/util/external/SystemUtil.java      |  31 ++++
 .../lookup2/ae/AbstractJCasTermAnnotator.java      |   2 +-
 .../lookup/ae/DictionaryLookupAnnotator.java       |   5 +-
 .../lookup/ae/UmlsDictionaryLookupAnnotator.java   |   4 +
 .../src/main/python => ctakes-examples}/.gitignore |   3 +-
 .../ctakes/examples/ctakes_cnlpt_py/README.md      |   0
 .../pipeline/CnlptNegation.piper}                  |  26 +++-
 .../ctakes/examples/ctakes_cnlpt_py}/setup.cfg     |  14 +-
 .../ctakes/examples/ctakes_cnlpt_py/setup.py       |   3 +
 .../ctakes_cnlpt_py/src/ctakes_cnlpt}/__init__.py  |   0
 .../src/ctakes_cnlpt/ae}/__init__.py               |   0
 .../src/ctakes_cnlpt/ae/negation_delegator.py      |  64 ++++++++
 .../src/ctakes_cnlpt/negation_pipeline.py          |  24 +++
 .../ctakes/examples/pipeline/PbjFirstStep.piper    |  19 ++-
 .../apache/ctakes/gui/component/SmoothToolTip.java |   5 +-
 ctakes-pbj/setup.py                                |   2 -
 .../org/apache/ctakes/pbj/ae/ArtemisStarter.java   |   4 +-
 .../org/apache/ctakes/pbj/ae/ArtemisStopper.java   |   4 +-
 .../java/org/apache/ctakes/pbj/ae/PbjPipper.java   | 103 +++++++++++++
 .../java/org/apache/ctakes/pbj/ae/PbjSender.java   |   4 +-
 .../apache/ctakes/pbj/util/ArtemisController.java  |  10 --
 .../org/apache/ctakes/pbj/ctakes_pbj_py/README.md  | 138 +++++++++++++++++
 .../ctakes/pbj/ctakes_pbj_py}/pyproject.toml       |   0
 .../org/apache/ctakes/pbj/ctakes_pbj_py}/setup.cfg |   8 +-
 .../org/apache/ctakes/pbj/ctakes_pbj_py/setup.py   |   3 +
 .../pbj/ctakes_pbj_py/src/ctakes_pbj}/__init__.py  |   0
 .../src/ctakes_pbj/component}/__init__.py          |   0
 .../src}/ctakes_pbj/component/cas_annotator.py     |   0
 .../src}/ctakes_pbj/component/pbj_receiver.py      |   3 +-
 .../src}/ctakes_pbj/component/pbj_sender.py        |   5 +-
 .../src/ctakes_pbj/examples}/__init__.py           |   0
 .../src}/ctakes_pbj/examples/sentence_printer.py   |   0
 .../examples/sentence_printer_pipeline.py          |   4 +-
 .../src}/ctakes_pbj/examples/word_finder.py        |   0
 .../ctakes_pbj/examples/word_finder_pipeline.py    |   0
 .../src/ctakes_pbj/pbj_tools}/__init__.py          |   0
 .../src/ctakes_pbj/pbj_tools}/arg_parser.py        |   2 +
 .../src}/ctakes_pbj/pbj_tools/create_relation.py   |   0
 .../src}/ctakes_pbj/pbj_tools/create_type.py       |   0
 .../src}/ctakes_pbj/pbj_tools/event_creator.py     |   0
 .../src}/ctakes_pbj/pbj_tools/get_common_types.py  |   0
 .../src}/ctakes_pbj/pbj_tools/helper_functions.py  |   0
 .../src}/ctakes_pbj/pbj_tools/token_tools.py       |   0
 .../src/ctakes_pbj/pipeline}/__init__.py           |   0
 .../src}/ctakes_pbj/pipeline/pbj_pipeline.py       |   0
 .../src/ctakes_pbj/scripts}/__init__.py            |   0
 .../src}/ctakes_pbj/scripts/get_typesystems.py     |   0
 .../src/ctakes_pbj/type_system}/__init__.py        |   0
 .../src}/ctakes_pbj/type_system/ctakes_const.py    |   0
 .../src}/ctakes_pbj/type_system/ctakes_types.py    |   0
 .../ctakes_pbj/type_system/type_system_loader.py   |   0
 .../apache/ctakes/pbj/pipeline/PbjStarter.piper    |  14 +-
 .../apache/ctakes/pbj/pipeline/PbjStopper.piper    |   1 +
 .../ae/features/NamedEntityFeaturesExtractor.java  |   7 +-
 69 files changed, 817 insertions(+), 160 deletions(-)

diff --git a/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/cr/XmiCollectionReaderCtakes.java b/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/cr/XmiCollectionReaderCtakes.java
index 28a11bd..2375394 100644
--- a/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/cr/XmiCollectionReaderCtakes.java
+++ b/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/cr/XmiCollectionReaderCtakes.java
@@ -36,6 +36,7 @@ import java.util.ArrayList;
 
 /**
  * A simple collection reader that reads CASes in XMI format from a directory in the filesystem.
+ * @deprecated Use XmiTreeReader in ctakes-core
  */
 @PipeBitInfo(
       name = "XMI in Dir Reader (2)",
@@ -43,6 +44,7 @@ import java.util.ArrayList;
       role = PipeBitInfo.Role.READER,
       products = { PipeBitInfo.TypeProduct.DOCUMENT_ID }
 )
+@Deprecated
 public class XmiCollectionReaderCtakes extends CollectionReader_ImplBase {
   /**
    * Name of configuration parameter that must be set to the path of a directory containing the XMI
@@ -65,6 +67,7 @@ public class XmiCollectionReaderCtakes extends CollectionReader_ImplBase {
   /**
    * @see org.apache.uima.collection.CollectionReader_ImplBase#initialize()
    */
+  @SuppressWarnings( "unchecked" )
   public void initialize() throws ResourceInitializationException {
 	mFailOnUnknownType = (Boolean) getConfigParameterValue(PARAM_FAILUNKNOWN);
 	if (null == mFailOnUnknownType) {
diff --git a/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/CasIndexer.java b/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/CasIndexer.java
index 88d3859..45a3978 100644
--- a/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/CasIndexer.java
+++ b/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/CasIndexer.java
@@ -51,7 +51,8 @@ public class CasIndexer<T extends Annotation>
   public CasIndexer()
   {
   }
-  
+
+  @SuppressWarnings( "unchecked" )
   public void initialize()
   {
     AnnotationIndex<Annotation> annotationIndex = null;
diff --git a/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/cleartk/windowed/context/FollowingContext.java b/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/cleartk/windowed/context/FollowingContext.java
index e87a89f..2df6622 100644
--- a/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/cleartk/windowed/context/FollowingContext.java
+++ b/ctakes-assertion/src/main/java/org/apache/ctakes/assertion/medfacts/cleartk/windowed/context/FollowingContext.java
@@ -44,6 +44,7 @@ public class FollowingContext extends AbstractLeftToRightContext {
     * {@inheritDoc}
     */
    @Override
+   @SuppressWarnings( "unchecked" )
    protected <T extends Annotation> List<T> select( final JCas jCas,
                                                     final Annotation focusAnnotation,
                                                     final Class<T> annotationClass,
diff --git a/ctakes-clinical-pipeline/src/main/java/org/apache/ctakes/clinicalpipeline/runtime/BagOfAnnotationsGenerator.java b/ctakes-clinical-pipeline/src/main/java/org/apache/ctakes/clinicalpipeline/runtime/BagOfAnnotationsGenerator.java
index b47ac94..0821409 100644
--- a/ctakes-clinical-pipeline/src/main/java/org/apache/ctakes/clinicalpipeline/runtime/BagOfAnnotationsGenerator.java
+++ b/ctakes-clinical-pipeline/src/main/java/org/apache/ctakes/clinicalpipeline/runtime/BagOfAnnotationsGenerator.java
@@ -86,7 +86,8 @@ public abstract class BagOfAnnotationsGenerator<T extends Annotation,K> {
 	}
 	
 	protected abstract K extractInformation(T t);
-	
+
+	@SuppressWarnings( "unchecked" )
 	private Class<T> getClassOfT() {
 		ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
 		return (Class<T>) superclass.getActualTypeArguments()[0];
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/AbstractCommandRunner.java b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/AbstractCommandRunner.java
new file mode 100644
index 0000000..455309d
--- /dev/null
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/AbstractCommandRunner.java
@@ -0,0 +1,128 @@
+package org.apache.ctakes.core.ae;
+
+import org.apache.ctakes.core.util.external.SystemUtil;
+import org.apache.log4j.Logger;
+import org.apache.uima.UimaContext;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.apache.uima.resource.ResourceInitializationException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author DJ , chip-nlp
+ * @since {2/1/2023}
+ */
+abstract public class AbstractCommandRunner extends PausableFileLoggerAE {
+
+   static private final Logger LOGGER = Logger.getLogger( "AbstractCommandRunner" );
+
+
+   // This parameter is not mandatory so that extending classes can have fixed commands.
+   static public final String CMD_PARAM = "Command";
+   static public final String CMD_DESC = "A full command line to be executed. Make sure to quote.";
+   @ConfigurationParameter(
+         name = CMD_PARAM,
+         description = CMD_DESC,
+         mandatory = false
+
+   )
+   private String _cmd;
+
+   static public final String CMD_DIR_PARAM = "CommandDir";
+   static public final String CMD_DIR_DESC = "The Command Executable's directory.";
+   @ConfigurationParameter(
+         name = CMD_DIR_PARAM,
+         description = CMD_DIR_DESC,
+         mandatory = false
+   )
+   private String _cmdDir;
+
+   static public final String DIR_PARAM = "WorkingDir";
+   static public final String DIR_DESC = "The Working Directory directory.";
+   @ConfigurationParameter(
+         name = DIR_PARAM,
+         description = DIR_DESC,
+         mandatory = false
+   )
+   private String _workDir;
+
+   static public final String PER_DOC_PARAM = "PerDoc";
+   static public final String PER_DOC_DESC = "yes to run the command once per document. Default is no.";
+   @ConfigurationParameter(
+         name = PER_DOC_PARAM,
+         description = PER_DOC_DESC,
+         defaultValue = "no",
+         mandatory = false
+   )
+   private String _perDoc;
+
+   static public final String LOG_NAME_PARAM = "Log";
+   static public final String LOG_NAME_DESC = "A name for the streaming logger.  Default is the Command.";
+   @ConfigurationParameter(
+         name = LOG_NAME_PARAM,
+         description = LOG_NAME_DESC,
+         mandatory = false
+   )
+   private String _logName;
+
+   /**
+    *
+    * @return true if the command must be explicitly set in the piper file.
+    */
+   protected boolean isCommandMandatory() {
+      return true;
+   }
+
+   protected String getCommand() {
+      return _cmd;
+   }
+
+   protected String getCommandDir() {
+      return _cmdDir;
+   }
+
+   protected String getWorkingDir() {
+      return _workDir;
+   }
+
+   protected boolean processPerDoc() {
+      return _perDoc.equalsIgnoreCase( "yes" ) || _perDoc.equalsIgnoreCase( "true" );
+   }
+
+   protected String getLogName() {
+      return _logName;
+   }
+
+   protected String getFullCommand() {
+      final String commandDir = getCommandDir();
+      final String command = getCommand();
+      return ( commandDir == null || commandDir.isEmpty() ) ? command : commandDir + File.separator + command;
+   }
+
+   public void logInfo( final String info ) {
+      LOGGER.info( info );
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void initialize( final UimaContext context ) throws ResourceInitializationException {
+      super.initialize( context );
+      _cmd = SystemUtil.subVariableParameters( _cmd, context );
+      _cmdDir = SystemUtil.subVariableParameters( _cmdDir, context );
+      _workDir = SystemUtil.subVariableParameters( _workDir, context );
+      if ( _cmdDir != null && !_cmdDir.isEmpty() && !new File( _cmdDir ).exists() ) {
+         LOGGER.warn( "Cannot find Command Directory " + _cmdDir );
+      }
+      if ( _workDir != null && !_workDir.isEmpty() && !new File( _workDir ).exists() ) {
+         LOGGER.warn( "Cannot find Working Directory " + _workDir );
+      }
+      if ( isCommandMandatory() && ( _cmd == null || _cmd.trim().isEmpty() ) ) {
+         throw new ResourceInitializationException( new IOException( "Parameter " + CMD_PARAM + " must be set." ) );
+      }
+   }
+
+
+}
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CommandRunner.java b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CommandRunner.java
index 5e25a3c..03c17aa 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CommandRunner.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CommandRunner.java
@@ -4,12 +4,13 @@ import org.apache.ctakes.core.pipeline.PipeBitInfo;
 import org.apache.ctakes.core.util.external.SystemUtil;
 import org.apache.log4j.Logger;
 import org.apache.uima.UimaContext;
+import org.apache.uima.analysis_engine.AnalysisEngineDescription;
 import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
 import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.apache.uima.fit.factory.AnalysisEngineFactory;
 import org.apache.uima.jcas.JCas;
 import org.apache.uima.resource.ResourceInitializationException;
 
-import java.io.File;
 import java.io.IOException;
 
 /**
@@ -21,66 +22,10 @@ import java.io.IOException;
       description = "Runs an external process.",
       role = PipeBitInfo.Role.SPECIAL
 )
-public class CommandRunner extends PausableFileLoggerAE {
+public class CommandRunner extends AbstractCommandRunner {
 
    static private final Logger LOGGER = Logger.getLogger( "CommandRunner" );
 
-   // to add a configuration parameter, type "param" and hit tab.
-   static public final String CMD_PARAM = "Command";
-   static public final String CMD_DESC = "A full command line to be executed. Make sure to quote.";
-   @ConfigurationParameter(
-         name = CMD_PARAM,
-         description = CMD_DESC
-   )
-   private String _cmd;
-
-   static public final String CMD_DIR_PARAM = "CommandDir";
-   static public final String CMD_DIR_DESC = "The Command Executable's directory.";
-   @ConfigurationParameter(
-         name = CMD_DIR_PARAM,
-         description = CMD_DIR_DESC,
-         mandatory = false
-   )
-   private String _cmdDir;
-
-   static public final String DIR_PARAM = "Dir";
-   static public final String DIR_DESC = "The Command's root directory.";
-   @ConfigurationParameter(
-         name = DIR_PARAM,
-         description = DIR_DESC,
-         mandatory = false
-   )
-   private String _dir;
-
-
-   static public final String PER_DOC_PARAM = "PerDoc";
-   static public final String PER_DOC_DESC = "yes to run the command once per document. Default is no.";
-   @ConfigurationParameter(
-         name = PER_DOC_PARAM,
-         description = PER_DOC_DESC,
-         defaultValue = "no",
-         mandatory = false
-   )
-   private String _perDoc;
-
-   static public final String WAIT_PARAM = "Wait";
-   static public final String WAIT_DESC = "Wait for the launched command to finish.  Default is no.";
-   @ConfigurationParameter(
-         name = WAIT_PARAM,
-         description = WAIT_DESC,
-         defaultValue = "no",
-         mandatory = false
-   )
-   private String _wait;
-
-   static public final String LOG_NAME_PARAM = "Log";
-   static public final String LOG_NAME_DESC = "A name for the streaming logger.  Default is the Command.";
-   @ConfigurationParameter(
-         name = LOG_NAME_PARAM,
-         description = LOG_NAME_DESC,
-         mandatory = false
-   )
-   private String _logName;
 
    static public final String SET_JAVAHOME_PARAM = "SetJavaHome";
    static public final String SET_JAVAHOME_DESC = "Set JAVA_HOME to the Java running cTAKES.  Default is yes.";
@@ -93,17 +38,11 @@ public class CommandRunner extends PausableFileLoggerAE {
    private String _setJavaHome;
 
 
-   protected boolean processPerDoc() {
-      return _perDoc.equalsIgnoreCase( "yes" ) || _perDoc.equalsIgnoreCase( "true" );
-   }
 
    protected boolean setJavaHome() {
       return _setJavaHome.equalsIgnoreCase( "yes" ) || _setJavaHome.equalsIgnoreCase( "true" );
    }
 
-   public void logInfo( final String info ) {
-      LOGGER.info( info );
-   }
 
    /**
     * {@inheritDoc}
@@ -111,15 +50,6 @@ public class CommandRunner extends PausableFileLoggerAE {
    @Override
    public void initialize( final UimaContext context ) throws ResourceInitializationException {
       super.initialize( context );
-      _cmdDir = SystemUtil.subVariableParameters( _cmdDir, context );
-      _dir = SystemUtil.subVariableParameters( _dir, context );
-      _cmd = SystemUtil.subVariableParameters( _cmd, context );
-      if ( _cmdDir != null && !_cmdDir.isEmpty() && !new File( _cmdDir ).exists() ) {
-         LOGGER.warn( "Cannot find Command Directory " + _cmdDir );
-      }
-      if ( _dir != null && !_dir.isEmpty() && !new File( _dir ).exists() ) {
-         LOGGER.warn( "Cannot find Directory " + _dir );
-      }
       if ( processPerDoc() ) {
          return;
       }
@@ -147,7 +77,7 @@ public class CommandRunner extends PausableFileLoggerAE {
 
 
     protected void runCommand() throws IOException {
-      final String command = ( _cmdDir == null || _cmdDir.isEmpty() ) ? _cmd : _cmdDir + File.separator + _cmd;
+      final String command = getFullCommand();
       final SystemUtil.CommandRunner runner = new SystemUtil.CommandRunner( command );
       final String logFile = getLogFile();
       if ( logFile != null && !logFile.isEmpty() ) {
@@ -156,14 +86,13 @@ public class CommandRunner extends PausableFileLoggerAE {
          final Logger logger = getRunLogger();
          runner.setLogger( logger );
       }
-      if ( _wait.equalsIgnoreCase( "yes" ) || _wait.equalsIgnoreCase( "true" ) ) {
-         runner.wait( true );
-      }
+      runner.wait( shouldWait() );
       if ( !setJavaHome() ) {
          runner.setSetJavaHome( false );
       }
-      if ( _dir != null && !_dir.isEmpty() ) {
-         runner.setDirectory( _dir );
+      final String workingDir = getWorkingDir();
+      if ( workingDir != null && !workingDir.isEmpty() ) {
+         runner.setDirectory( workingDir );
       }
       LOGGER.info( "Running " + command + " ..." );
       if ( logFile != null && !logFile.isEmpty() ) {
@@ -174,15 +103,22 @@ public class CommandRunner extends PausableFileLoggerAE {
    }
 
    private Logger getRunLogger() {
-      if ( _logName != null && !_logName.isEmpty() ) {
-         return Logger.getLogger( _logName );
+      final String logName = getLogName();
+      if ( logName != null && !logName.isEmpty() ) {
+         return Logger.getLogger( logName );
       }
-      final int spaceIndex = _cmd.indexOf( ' ' );
+      final String command = getCommand().trim();
+      final int spaceIndex = command.indexOf( ' ' );
       if ( spaceIndex < 0 ) {
-         return Logger.getLogger( _cmd );
+         return Logger.getLogger( command );
       }
-      return Logger.getLogger( _cmd.substring( 0, spaceIndex ) );
+      return Logger.getLogger( command.substring( 0, spaceIndex ) );
    }
 
+   static public AnalysisEngineDescription createEngineDescription( final String command )
+         throws ResourceInitializationException {
+      return AnalysisEngineFactory.createEngineDescription( CommandRunner.class,
+                                                            AbstractCommandRunner.CMD_PARAM, command );
+   }
 
 }
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CtakesRunner.java b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CtakesRunner.java
index 141ad71..99bf594 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CtakesRunner.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/CtakesRunner.java
@@ -27,13 +27,13 @@ public class CtakesRunner extends PausableFileLoggerAE {
 
    static private final Logger LOGGER = Logger.getLogger( "CtakesRunner" );
 
-   static public final String CLI_PARAM = "Pipe";
-   static public final String CLI_DESC = "Piper parameters. Make sure to quote.";
+   static public final String PIPE_PARAM = "Pipeline";
+   static public final String PIPE_DESC = "Piper parameters. Make sure to quote.";
    @ConfigurationParameter(
-         name = CLI_PARAM,
-         description = CLI_DESC
+         name = PIPE_PARAM,
+         description = PIPE_DESC
    )
-   private String _cli;
+   private String _pipeline;
 
 
    static private final String JAVA_CMD = "-Xms512M -Xmx3g org.apache.ctakes.core.pipeline.PiperFileRunner";
@@ -55,7 +55,7 @@ public class CtakesRunner extends PausableFileLoggerAE {
    @Override
    public void initialize( final UimaContext context ) throws ResourceInitializationException {
       super.initialize( context );
-      _cli = SystemUtil.subVariableParameters( _cli, context );
+      _pipeline = SystemUtil.subVariableParameters( _pipeline, context );
       try {
          runCommand();
       } catch ( IOException ioE ) {
@@ -92,15 +92,15 @@ public class CtakesRunner extends PausableFileLoggerAE {
 
 
    private String getPiper() throws IOException {
-      final int pIndex = _cli.indexOf( "-p " );
+      final int pIndex = _pipeline.indexOf( "-p " );
       if ( pIndex < 0 ) {
-         throw new IOException( "Improper Piper Runner Specification " + _cli );
+         throw new IOException( "Improper Piper Runner Specification " + _pipeline );
       }
-      final int spaceIndex = _cli.indexOf( ' ', pIndex + 4 );
+      final int spaceIndex = _pipeline.indexOf( ' ', pIndex + 4 );
       if ( spaceIndex < 4 ) {
-         throw new IOException( "Improper Piper Runner Specification " + _cli );
+         throw new IOException( "Improper Piper Runner Specification " + _pipeline );
       }
-      String piper = _cli.substring( pIndex + 3, spaceIndex );
+      String piper = _pipeline.substring( pIndex + 3, spaceIndex );
       int slashIndex = piper.lastIndexOf( '/' );
       if ( slashIndex < 0 ) {
          slashIndex = piper.lastIndexOf( '\\' );
@@ -118,11 +118,11 @@ public class CtakesRunner extends PausableFileLoggerAE {
       final String java_home = System.getProperty( "java.home" );
       final SystemUtil.CommandRunner runner =
             new SystemUtil.CommandRunner( "\"" + java_home + File.separator + "bin" + File.separator
-                                          + "java\" " + JAVA_CMD + " " + _cli );
+                                          + "java\" " + JAVA_CMD + " " + _pipeline );
       final String logFile = getLogFile();
       runner.setLogFiles( logFile );
 //      LOGGER.info( "Starting cTAKES with " + _cli + " ..." );
-      LOGGER.info( "Starting external cTAKES pipeline with " + _cli + " ..." );
+      LOGGER.info( "Starting external cTAKES pipeline with " + _pipeline + " ..." );
       SystemUtil.run( runner );
       pause();
    }
@@ -130,7 +130,7 @@ public class CtakesRunner extends PausableFileLoggerAE {
 
    static public AnalysisEngineDescription createEngineDescription( final String pipe )
          throws ResourceInitializationException {
-      return AnalysisEngineFactory.createEngineDescription( CtakesRunner.class, CtakesRunner.CLI_PARAM, pipe );
+      return AnalysisEngineFactory.createEngineDescription( CtakesRunner.class, CtakesRunner.PIPE_PARAM, pipe );
    }
 
 
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/PythonRunner.java b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/PythonRunner.java
new file mode 100644
index 0000000..ad32683
--- /dev/null
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/PythonRunner.java
@@ -0,0 +1,164 @@
+package org.apache.ctakes.core.ae;
+
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.ctakes.core.util.external.SystemUtil;
+import org.apache.log4j.Logger;
+import org.apache.uima.UimaContext;
+import org.apache.uima.analysis_engine.AnalysisEngineDescription;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.apache.uima.fit.factory.AnalysisEngineFactory;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.resource.ResourceInitializationException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author SPF , chip-nlp
+ * @since {5/10/2022}
+ */
+@PipeBitInfo(
+      name = "PythonRunner",
+      description = "Starts a Python process with the given parameters.",
+      role = PipeBitInfo.Role.SPECIAL
+)
+public class PythonRunner extends AbstractCommandRunner {
+
+   static private final Logger LOGGER = Logger.getLogger( "PythonRunner" );
+
+   static public final String VENV_PARAM = "VirtualEnv";
+   static public final String VENV_DESC = "Path to Python virtual environment.";
+   @ConfigurationParameter(
+         name = VENV_PARAM,
+         description = VENV_DESC,
+         mandatory = false
+   )
+   private String _venv;
+
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void initialize( final UimaContext context ) throws ResourceInitializationException {
+      super.initialize( context );
+      _venv = SystemUtil.subVariableParameters( _venv, context );
+      if ( _venv != null && !_venv.isEmpty() && !new File( _venv ).exists() ) {
+         LOGGER.warn( "Cannot find Virtual Environment Directory " + _venv );
+      }
+      if ( processPerDoc() ) {
+         return;
+      }
+      try {
+         runCommand();
+      } catch ( IOException ioE ) {
+         throw new ResourceInitializationException( ioE );
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void process( final JCas jcas ) throws AnalysisEngineProcessException {
+      if ( !processPerDoc() ) {
+         return;
+      }
+      try {
+         runCommand();
+      } catch ( IOException ioE ) {
+         throw new AnalysisEngineProcessException( ioE );
+      }
+   }
+
+
+   private String getModule() {
+      final String command = getCommand().trim();
+      final int dashMindex = command.indexOf( "-m " );
+      if ( dashMindex >= 0 ) {
+         final int spaceIndex = command.indexOf( ' ', dashMindex + 3 );
+         if ( spaceIndex > 0 ) {
+            return command.substring( dashMindex + 3, spaceIndex );
+         }
+         return command.substring( dashMindex + 3 );
+      }
+      final int spaceIndex = command.indexOf( ' ' );
+      if ( spaceIndex < 0 ) {
+         return command;
+      }
+      return command.substring( 0, spaceIndex );
+   }
+
+   private String getModuleName() {
+      String module = getModule();
+      if ( module.endsWith( ".py" ) ) {
+         module = module.substring( 0, module.length()-3 );
+      }
+      int slashIndex = module.lastIndexOf( '/' );
+      if ( slashIndex < 0 ) {
+         slashIndex = module.lastIndexOf( '\\' );
+      }
+      if ( slashIndex < 0 ) {
+         slashIndex = module.lastIndexOf( '.' );
+      }
+      if ( slashIndex >= 0 ) {
+         return module.substring( slashIndex + 1 );
+      }
+      return module;
+   }
+
+   protected String getFullCommand() {
+      final String commandDir = getCommandDir();
+      final String command = getCommand();
+      return ( commandDir == null || commandDir.isEmpty() )
+             ? "python " + command
+             : commandDir + File.separator + "python " + command;
+   }
+
+   protected void runCommand() throws IOException {
+      final String command = getFullCommand();
+      final SystemUtil.CommandRunner runner = new SystemUtil.CommandRunner( command );
+      final String logFile = getLogFile();
+      if ( logFile != null && !logFile.isEmpty() ) {
+         runner.setLogFiles( logFile );
+      } else {
+         final Logger logger = getRunLogger();
+         runner.setLogger( logger );
+      }
+      runner.wait( shouldWait() );
+      final String workingDir = getWorkingDir();
+      if ( workingDir != null && !workingDir.isEmpty() ) {
+         runner.setDirectory( workingDir );
+      }
+      if ( _venv != null && !_venv.trim().isEmpty() ) {
+         runner.setVenv( _venv );
+      }
+      LOGGER.info( "Starting " + command + " ..." );
+      if ( logFile != null && !logFile.isEmpty() ) {
+         LOGGER.info( "Log File is " + logFile );
+      }
+      SystemUtil.run( runner );
+      pause();
+   }
+
+   private Logger getRunLogger() {
+      final String logName = getLogName();
+      if ( logName != null && !logName.isEmpty() ) {
+         return Logger.getLogger( logName );
+      }
+      return Logger.getLogger( getModuleName() );
+   }
+
+
+   static public AnalysisEngineDescription createEngineDescription( final String venv,
+                                                                    final String command )
+         throws ResourceInitializationException {
+      return AnalysisEngineFactory.createEngineDescription( PythonRunner.class,
+                                                            PythonRunner.VENV_PARAM, venv,
+                                                            AbstractCommandRunner.CMD_PARAM, command );
+   }
+
+
+}
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/inert/PausableAE.java b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/inert/PausableAE.java
index bc6524c..11c5b9c 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/ae/inert/PausableAE.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/ae/inert/PausableAE.java
@@ -1,8 +1,6 @@
 package org.apache.ctakes.core.ae.inert;
 
-import org.apache.ctakes.core.pipeline.PipeBitInfo;
 import org.apache.ctakes.core.util.log.DotLogger;
-import org.apache.log4j.Logger;
 import org.apache.uima.UimaContext;
 import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
 import org.apache.uima.fit.descriptor.ConfigurationParameter;
@@ -26,6 +24,16 @@ abstract public class PausableAE extends JCasAnnotator_ImplBase {
    )
    private int _pause = 0;
 
+   static public final String WAIT_PARAM = "Wait";
+   static public final String WAIT_DESC = "Wait for the process to finish.  Default is no.";
+   @ConfigurationParameter(
+         name = WAIT_PARAM,
+         description = WAIT_DESC,
+         defaultValue = "no",
+         mandatory = false
+   )
+   private String _wait;
+
    /**
     * {@inheritDoc}
     */
@@ -36,6 +44,10 @@ abstract public class PausableAE extends JCasAnnotator_ImplBase {
 
    protected void logInfo( final String info ) {}
 
+   protected boolean shouldWait() {
+      return _wait.equalsIgnoreCase( "yes" ) || _wait.equalsIgnoreCase( "true" );
+   }
+
    final protected void pause() {
       if ( _pause < 1 ) {
          return;
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/cr/JdbcCollectionReader.java b/ctakes-core/src/main/java/org/apache/ctakes/core/cr/JdbcCollectionReader.java
index f1a7c3c..676b312 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/cr/JdbcCollectionReader.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/cr/JdbcCollectionReader.java
@@ -182,6 +182,7 @@ public class JdbcCollectionReader extends JCasCollectionReader_ImplBase {
     * @param valueFile -
     * @throws IOException -
     */
+   @SuppressWarnings( "unchecked" )
    private void loadValueFile( File valueFile ) throws IOException {
       List<String> lineList = new ArrayList<>();
       BufferedReader br = new BufferedReader( new FileReader( valueFile ) );
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/cr/jdbc/JdbcNotesReader.java b/ctakes-core/src/main/java/org/apache/ctakes/core/cr/jdbc/JdbcNotesReader.java
index 8c7d5df..435faa5 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/cr/jdbc/JdbcNotesReader.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/cr/jdbc/JdbcNotesReader.java
@@ -812,6 +812,7 @@ final public class JdbcNotesReader extends JCasCollectionReader_ImplBase {
     * @return a decryptor
     * @throws ResourceInitializationException -
     */
+   @SuppressWarnings( "unchecked" )
    static private Decryptor createWrappedDecryptor( final Class decryptorThingClass )
          throws ResourceInitializationException {
       final Object[] emptyObjectArray = new Object[ 0 ];
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java b/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java
index ab0320a..cf8abd8 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/CliOptionalsHandler.java
@@ -43,6 +43,8 @@ final public class CliOptionalsHandler {
             return optionals.getHtmlOutDirectory();
          case StandardCliOptions.SUB_DIR:
             return optionals.getSubDirectory();
+         case StandardCliOptions.PIP_PBJ:
+            return optionals.getPipPbj();
          case "a":
             return optionals.getOption_a();
          case "b":
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PipeBitLocator.java b/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PipeBitLocator.java
index fb2e36c..817b23b 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PipeBitLocator.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/PipeBitLocator.java
@@ -22,6 +22,7 @@ import java.util.stream.Collectors;
  * @version %I%
  * @since 11/18/2017
  */
+@SuppressWarnings( "unchecked" )
 public enum PipeBitLocator {
    INSTANCE;
 
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java b/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java
index 4130019..f158162 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/pipeline/StandardCliOptions.java
@@ -21,6 +21,7 @@ public interface StandardCliOptions {
    static public final String SUB_DIR = "subDir";
    static public final String XMI_OUT_DIR = "xmiOut";
    static public final String HTML_OUT_DIR = "htmlOut";
+   static public final String PIP_PBJ = "pipPbj";
 
 
    @Option(
@@ -89,6 +90,12 @@ public interface StandardCliOptions {
          defaultValue = "" )
    String getUmlsApiKey();
 
+   @Option(
+         longName = PIP_PBJ,
+         description = "pip ctakes-PBJ.",
+         defaultValue = "yes" )
+   String getPipPbj();
+
 
    @Option(
          shortName = "?",
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/util/ListIterable.java b/ctakes-core/src/main/java/org/apache/ctakes/core/util/ListIterable.java
index b5f8b22..2000f6e 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/util/ListIterable.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/util/ListIterable.java
@@ -29,7 +29,8 @@ class FSListIterator<T> implements Iterator<T> {
   public boolean hasNext() {
     return (list instanceof NonEmptyFSList);
   }
-  
+
+  @SuppressWarnings( "unchecked" )
   public T next() {
     T element = (T) ((NonEmptyFSList)list).getHead();
     list = ((NonEmptyFSList)list).getTail();
diff --git a/ctakes-core/src/main/java/org/apache/ctakes/core/util/external/SystemUtil.java b/ctakes-core/src/main/java/org/apache/ctakes/core/util/external/SystemUtil.java
index 67c10e1..2de3500 100644
--- a/ctakes-core/src/main/java/org/apache/ctakes/core/util/external/SystemUtil.java
+++ b/ctakes-core/src/main/java/org/apache/ctakes/core/util/external/SystemUtil.java
@@ -332,6 +332,7 @@ final public class SystemUtil {
       private boolean _stopOnExit;
       private InputFeeder _inputFeeder;
       private boolean _setJavaHome = true;
+      private String _venv;
 
       public CommandRunner( final String command ) {
          _command = command;
@@ -374,6 +375,10 @@ final public class SystemUtil {
          _setJavaHome = setJavaHome;
       }
 
+      public void setVenv( final String venv ) {
+         _venv = venv;
+      }
+
       private String getDefaultLogFile() {
          final String ext = String.valueOf( new Random().nextLong() );
          final int spaceIndex = _command.indexOf( ' ' );
@@ -416,6 +421,32 @@ final public class SystemUtil {
             }
          }
          env.putAll( _userEnvVars );
+         if ( _venv != null && !_venv.trim().isEmpty() ) {
+            env.put( "VIRTUAL_ENV", _venv );
+            final String WinPath = env.get( "Path" );
+            if ( WinPath != null ) {
+               env.put( "Path", getVenvPath() + WinPath );
+            }
+            final String UxPath = env.get( "PATH" );
+            if ( UxPath != null ) {
+               env.put( "PATH", getVenvPath() + UxPath );
+            }
+         }
+      }
+
+      static private final String[] VENV_EXTENSIONS
+            = { "Library/mingw-w64/bin", "Library/usr/bin", "Library/bin", "Scripts", "bin", "lib/site-packages" };
+
+      private String getVenvPath() {
+         final StringBuilder sb = new StringBuilder( _venv + File.pathSeparator );
+         for ( String extension : VENV_EXTENSIONS ) {
+            final String envPath = _venv + File.separator + extension.replace( '/', File.separatorChar );
+            if ( new File( envPath ).isDirectory() ) {
+               sb.append( envPath )
+                   .append( File.pathSeparator );
+            }
+         }
+         return sb.toString();
       }
 
       public Boolean call() throws IOException, InterruptedException {
diff --git a/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/ae/AbstractJCasTermAnnotator.java b/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/ae/AbstractJCasTermAnnotator.java
index de73a93..7db44c1 100644
--- a/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/ae/AbstractJCasTermAnnotator.java
+++ b/ctakes-dictionary-lookup-fast/src/main/java/org/apache/ctakes/dictionary/lookup2/ae/AbstractJCasTermAnnotator.java
@@ -94,6 +94,7 @@ abstract public class AbstractJCasTermAnnotator extends JCasAnnotator_ImplBase
     * {@inheritDoc}
     */
    @Override
+   @SuppressWarnings( "unchecked" )
    public void initialize( final UimaContext uimaContext ) throws ResourceInitializationException {
       super.initialize( uimaContext );
       try {
@@ -109,7 +110,6 @@ abstract public class AbstractJCasTermAnnotator extends JCasAnnotator_ImplBase
       }
 
       LOGGER.info( "Using dictionary lookup window type: " + _windowClassName );
-//      _lookupWindowType = JCasUtil.getType( _windowClassName );
       final String[] tagArr = _exclusionPosTags.split( "," );
       for ( String tag : tagArr ) {
          _exclusionPartsOfSpeech.add( tag.toUpperCase() );
diff --git a/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/DictionaryLookupAnnotator.java b/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/DictionaryLookupAnnotator.java
index 3d5e04b..a81c095 100644
--- a/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/DictionaryLookupAnnotator.java
+++ b/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/DictionaryLookupAnnotator.java
@@ -60,6 +60,7 @@ import org.apache.uima.resource.ResourceInitializationException;
 		dependencies = { PipeBitInfo.TypeProduct.CHUNK, PipeBitInfo.TypeProduct.BASE_TOKEN },
 		products = PipeBitInfo.TypeProduct.IDENTIFIED_ANNOTATION
 )
+@Deprecated
 public class DictionaryLookupAnnotator extends JCasAnnotator_ImplBase
 {
 	// LOG4J logger based on class name
@@ -82,7 +83,9 @@ public class DictionaryLookupAnnotator extends JCasAnnotator_ImplBase
 
 		iv_context = aContext;
 		configInit();
-
+		iv_logger.info( "\nThe ctakes-dictionary-lookup module has been deprecated.\n"
+							 + "Please consider using ctakes-dictionary-lookup-fast.\n"
+							 + "ctakes-dictionary-lookup-fast is better than or equal in accuracy but ~1000x faster." );
 	}
 
 	/**
diff --git a/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/UmlsDictionaryLookupAnnotator.java b/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/UmlsDictionaryLookupAnnotator.java
index 2b5743d..10c34f8 100644
--- a/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/UmlsDictionaryLookupAnnotator.java
+++ b/ctakes-dictionary-lookup/src/main/java/org/apache/ctakes/dictionary/lookup/ae/UmlsDictionaryLookupAnnotator.java
@@ -46,6 +46,9 @@ import java.net.URLEncoder;
  * UIMA annotator that identified entities based on lookup.
  *
  * @author Mayo Clinic
+ *
+ * @deprecated Use the dictionary-lookup-fast module.
+ * It is much faster and the same or better accuracy according to tests on multiple annotated corpora.
  */
 @PipeBitInfo(
       name = "UMLS Dictionary Lookup (Old)",
@@ -53,6 +56,7 @@ import java.net.URLEncoder;
       dependencies = { PipeBitInfo.TypeProduct.CHUNK, PipeBitInfo.TypeProduct.BASE_TOKEN },
       products = PipeBitInfo.TypeProduct.IDENTIFIED_ANNOTATION
 )
+@Deprecated
 public class UmlsDictionaryLookupAnnotator extends DictionaryLookupAnnotator {
    /* Special implementation to pre bundle the UMLS SnowmedCT/RxNorm dictionaries
     * Performs a check for user's UMLS licence at init time via their RESTful API
diff --git a/ctakes-pbj/src/main/python/.gitignore b/ctakes-examples/.gitignore
similarity index 98%
rename from ctakes-pbj/src/main/python/.gitignore
rename to ctakes-examples/.gitignore
index 87a9636..b28ac39 100644
--- a/ctakes-pbj/src/main/python/.gitignore
+++ b/ctakes-examples/.gitignore
@@ -1,6 +1,7 @@
 # IntelliJ project and target
 /.idea/
-ctakes-pbj.iml
+target/
+ctakes-examples.iml
 
 # Byte-compiled / optimized / DLL files
 __pycache__/
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/__init__.py b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/README.md
similarity index 100%
copy from ctakes-pbj/src/main/python/ctakes_pbj/__init__.py
copy to ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/README.md
diff --git a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/pipeline/CnlptNegation.piper
similarity index 55%
copy from ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper
copy to ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/pipeline/CnlptNegation.piper
index c061268..5bf9efe 100644
--- a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper
+++ b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/pipeline/CnlptNegation.piper
@@ -7,9 +7,21 @@
 #  This piper will then launch another instance of Apache cTAKES.
 #  That instance of cTAKES will run the third and final bit of the entire PBJ pipeline.
 #
-#  This piper will then launch a python PBJ bit of the entire pipeline.
+#  This piper will then launch a python PBJ pipeline that runs the negation model from the external project
+#  Clinical NLP Transformers (cnlp_transformers), which can be found at
+#  https://github.com/Machine-Learning-for-Medical-Language/cnlp_transformers
 #
 
+#
+#  To run this pipeline from the command line, use the parameters:
+#  -p PbjFirstStep
+#  -d {python environment Directory}
+#  -a {Artemis Broker Directory}
+#  -i {Input Document Directory}
+#  -o {Output Directory}
+#
+
+//  Sets up required parameters, starts your Artemis Broker, pips the PBJ project.
 load PbjStarter
 
 //
@@ -18,19 +30,20 @@ load PbjStarter
 // $ArtemisBroker will substitute the value of this cTAKES pipeline's value for ArtemisBroker.
 //
 
-add CtakesRunner Pipe="-p PbjThirdStep -o $OutputDirectory -a $ArtemisBroker"
+add CtakesRunner Pipeline="-p PbjThirdStep -o $OutputDirectory -a $ArtemisBroker"
 
 
 //
 // Start the python bit of the full pipeline.
-// pip the dependency packages if your environment doesn't have them.
 //
-// Declare the python pipeline defining the second step in the total pipeline.
-set PbjSecondStep=ctakes-pbj/src/main/python/ctakes_pbj/examples/word_finder_pipeline.py
+
+// pip the cnlp_transformers project and its dependencies.
+add PythonRunner Command="-m pip install resources/org/apache/ctakes/examples/ctakes_cnlpt_py/" Wait=yes
+
 
 // There is a fixed order to queue specification in python pipelines.
 // The incoming (receiver) queue is named first, the outgoing (sender) queue is named second.
-add CommandRunner Command="python $PbjSecondStep JavaToPy PyToJava" LogFile=word_finder_pipeline.log
+add PythonRunner Command="-m ctakes_cnlpt.negation_pipeline JavaToPy PyToJava --output_dir $OutputDirectory" LogFile=negation_pipeline.log
 
 
 //
@@ -39,6 +52,7 @@ add CommandRunner Command="python $PbjSecondStep JavaToPy PyToJava" LogFile=word
 
 // Load a simple token processing pipeline from another pipeline file
 load DefaultTokenizerPipeline
+load DictionarySubPipe
 
 // Send CAS to Artemis at the specified queue.  Send stop signal when processing has finished.
 add PbjSender SendQueue=JavaToPy SendStop=yes
diff --git a/ctakes-pbj/setup.cfg b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/setup.cfg
similarity index 76%
copy from ctakes-pbj/setup.cfg
copy to ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/setup.cfg
index 59459da..33c58a8 100644
--- a/ctakes-pbj/setup.cfg
+++ b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/setup.cfg
@@ -1,9 +1,9 @@
 [metadata]
-name = ctakes_pbj
-version = 5.0
+name = ctakes-cnlpt
+version = 5.0.0
 author = Apache cTAKES
 author_email = dev@ctakes.apache.org
-description = Apache cTAKES Python Bridge to Java
+description = Apache cTAKES Clinical NLP Transformers example
 long_description = file: README.md
 long_description_content_type = text/markdown
 url = https://github.com/apache/ctakes
@@ -17,12 +17,12 @@ classifiers =
 
 [options]
 package_dir=
-    = src/main/python
+    = src
 packages = find:
 python_requires = >=3.7, <3.9
 install_requires =
-    dkpro-cassis~=0.7.0
-    stomp.py~=8.0.0
+    ctakes_pbj~=5.0.0
+    cnlp-transformers~=0.4.0
 
 [options.packages.find]
-where = src/main/python
+where = src
diff --git a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/setup.py b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/setup.py
new file mode 100644
index 0000000..bf36da8
--- /dev/null
+++ b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/setup.py
@@ -0,0 +1,3 @@
+from distutils.core import setup
+from setuptools import find_packages
+setup(name='ctakes_cnlpt', version='5.0.0', packages=find_packages())
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/component/__init__.py b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/component/__init__.py
rename to ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/examples/__init__.py b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/ae/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/examples/__init__.py
rename to ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/ae/__init__.py
diff --git a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/ae/negation_delegator.py b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/ae/negation_delegator.py
new file mode 100644
index 0000000..bed2486
--- /dev/null
+++ b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/ae/negation_delegator.py
@@ -0,0 +1,64 @@
+from ctakes_pbj.component import cas_annotator
+from ctakes_pbj.type_system import ctakes_types
+import asyncio
+from cnlpt.api.cnlp_rest import EntityDocument
+import cnlpt.api.negation_rest as negation_rest
+import time
+from ctakes_pbj.pbj_tools.helper_functions import *
+
+sem = asyncio.Semaphore(1)
+
+
+class NegationDelegator(cas_annotator.CasAnnotator):
+
+    # Initializes the cNLPT, which loads its Negation model.
+    def initialize(self):
+        print("Initializing cnlp-transformers negation " + str(time.time()) + " ...")
+        asyncio.run(self.init_caller())
+        print("Done " + str(time.time()))
+
+    # Processes the document to get Negation on Events from cNLPT.
+    def process(self, cas):
+        event_mentions = cas.select(ctakes_types.EventMention)
+        offsets = create_offset(event_mentions)
+
+        print("Calling cnlp-transformers negation " + str(time.time()) + " ...")
+        asyncio.run(self.negation_caller(cas, event_mentions, offsets))
+        print("Done " + str(time.time()))
+
+    # def process2(self, cas):
+    #     sentences = cas.select(ctakes_types.Sentence)
+    #     event_mentions = cas.select(ctakes_types.EventMention)
+    #     print("Calling cnlp-transformers negation " + str(time.time()) + " ...")
+    #     asyncio.run(self.negation_caller2(cas, sentences, event_mentions))
+    #     print("Done " + str(time.time()))
+
+    async def init_caller(self):
+        await negation_rest.startup_event()
+
+    async def negation_caller(self, cas, event_mentions, offsets):
+        text = cas.sofa_string
+        eDoc = EntityDocument(doc_text=text, entities=offsets)
+
+        #async with sem:
+        negation_output = await negation_rest.process(eDoc)
+        i = 0
+        for e in event_mentions:
+            # -1 represents that it had happened, 1 represents that it is negated
+            e.polarity = negation_output.statuses[i] * -1
+            i += 1
+
+
+    # async def negation_caller2(self, cas, sentences, event_mentions):
+    #     for sentence in sentences:
+    #         text = sentence.get_covered_text()
+    #
+    #     eDoc = EntityDocument(doc_text=text, entities=offsets)
+    #
+    #     #async with sem:
+    #     negation_output = await negation_rest.process(eDoc)
+    #     i = 0
+    #     for e in event_mentions:
+    #         # -1 represents that it had happened, 1 represents that it is negated
+    #         e.polarity = negation_output.statuses[i] * -1
+    #         i += 1
diff --git a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/negation_pipeline.py b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/negation_pipeline.py
new file mode 100644
index 0000000..3375278
--- /dev/null
+++ b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/ctakes_cnlpt_py/src/ctakes_cnlpt/negation_pipeline.py
@@ -0,0 +1,24 @@
+import warnings
+from ctakes_pbj.component.pbj_receiver import start_receiver
+from ctakes_pbj.component.pbj_sender import PBJSender
+from ctakes_pbj.pipeline.pbj_pipeline import PBJPipeline
+from ctakes_cnlpt.ae.negation_delegator import NegationDelegator
+
+
+warnings.filterwarnings("ignore")
+
+
+def main():
+
+    # Create a new PBJ Pipeline, add a class that interacts with cNLPT to add Negation to Events.
+    pipeline = PBJPipeline()
+    pipeline.add(NegationDelegator())
+    # Add a PBJ Sender to the end of the pipeline to send the processed cas back to cTAKES and initialize the pipeline.
+    pipeline.add(PBJSender())
+    pipeline.initialize()
+    # Start a PBJ receiver to accept cas objects from Artemis and process them in the pipeline.
+    start_receiver(pipeline)
+
+
+main()
+
diff --git a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper
index c061268..077fe5c 100644
--- a/ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper
+++ b/ctakes-examples/src/user/resources/org/apache/ctakes/examples/pipeline/PbjFirstStep.piper
@@ -10,6 +10,17 @@
 #  This piper will then launch a python PBJ bit of the entire pipeline.
 #
 
+#
+#  To run this pipeline from the command line, use the parameters:
+#  -p PbjFirstStep
+#  -d {python environment Directory}
+#  -a {Artemis Broker Directory}
+#  -i {Input Document Directory}
+#  -o {Output Directory}
+#
+
+
+//  Sets up required parameters, starts your Artemis Broker, pips the PBJ project.
 load PbjStarter
 
 //
@@ -18,19 +29,19 @@ load PbjStarter
 // $ArtemisBroker will substitute the value of this cTAKES pipeline's value for ArtemisBroker.
 //
 
-add CtakesRunner Pipe="-p PbjThirdStep -o $OutputDirectory -a $ArtemisBroker"
+add CtakesRunner Pipeline="-p PbjThirdStep -o $OutputDirectory -a $ArtemisBroker"
 
 
 //
 // Start the python bit of the full pipeline.
-// pip the dependency packages if your environment doesn't have them.
 //
+
 // Declare the python pipeline defining the second step in the total pipeline.
-set PbjSecondStep=ctakes-pbj/src/main/python/ctakes_pbj/examples/word_finder_pipeline.py
+set PbjSecondStep=ctakes_pbj.examples.word_finder_pipeline
 
 // There is a fixed order to queue specification in python pipelines.
 // The incoming (receiver) queue is named first, the outgoing (sender) queue is named second.
-add CommandRunner Command="python $PbjSecondStep JavaToPy PyToJava" LogFile=word_finder_pipeline.log
+add PythonRunner Command="-m $PbjSecondStep JavaToPy PyToJava" LogFile=word_finder_pipeline.log
 
 
 //
diff --git a/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/SmoothToolTip.java b/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/SmoothToolTip.java
index 0d21a3d..f5d5d07 100644
--- a/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/SmoothToolTip.java
+++ b/ctakes-gui/src/main/java/org/apache/ctakes/gui/component/SmoothToolTip.java
@@ -1,7 +1,7 @@
 package org.apache.ctakes.gui.component;
 
 
-import sun.swing.SwingUtilities2;
+//import sun.swing.SwingUtilities2;
 
 import javax.swing.*;
 import javax.swing.plaf.ToolTipUI;
@@ -92,7 +92,8 @@ public class SmoothToolTip extends JToolTip {
       @Override
       public void paint( final Graphics g, final JComponent comp ) {
          final Font font = comp.getFont();
-         final FontMetrics metrics = SwingUtilities2.getFontMetrics( comp, g, font );
+//         final FontMetrics metrics = SwingUtilities2.getFontMetrics( comp, g, font );
+         final FontMetrics metrics = comp.getFontMetrics( font );
          final Dimension size = comp.getSize();
 
          final Color background = Color.YELLOW;//c.getBackground();
diff --git a/ctakes-pbj/setup.py b/ctakes-pbj/setup.py
deleted file mode 100644
index 0785324..0000000
--- a/ctakes-pbj/setup.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from distutils.core import setup
-setup(name='ctakes-pbj', version='5.0.0', packages=['ctakes_pbj'])
diff --git a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStarter.java b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStarter.java
index f8da0c5..6c46798 100644
--- a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStarter.java
+++ b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStarter.java
@@ -58,9 +58,7 @@ public class ArtemisStarter extends ArtemisController {
       final String logFile = getLogFile();
       runner.setLogFiles( logFile );
       runner.setDirectory( _artemisRoot );
-      if ( _wait.equalsIgnoreCase( "yes" ) || _wait.equalsIgnoreCase( "true" ) ) {
-         runner.wait( true );
-      }
+      runner.wait( shouldWait() );
       runner.setSetJavaHome( false );
       LOGGER.info( "Starting Apache Artemis ..." );
       SystemUtil.run( runner );
diff --git a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStopper.java b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStopper.java
index 8327610..07ed209 100644
--- a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStopper.java
+++ b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/ArtemisStopper.java
@@ -72,9 +72,7 @@ public class ArtemisStopper extends ArtemisController {
         final String logFile = getLogFile();
         runner.setLogFiles( logFile );
         runner.setDirectory( _artemisRoot );
-        if ( _wait.equalsIgnoreCase( "yes" ) || _wait.equalsIgnoreCase( "true" ) ) {
-            runner.wait( true );
-        }
+        runner.wait( shouldWait() );
         runner.setSetJavaHome( false );
         LOGGER.info( "Stopping Apache Artemis ..." );
         SystemUtil.run( runner );
diff --git a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjPipper.java b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjPipper.java
new file mode 100644
index 0000000..a8ed9b2
--- /dev/null
+++ b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjPipper.java
@@ -0,0 +1,103 @@
+package org.apache.ctakes.pbj.ae;
+
+import org.apache.ctakes.core.ae.PythonRunner;
+import org.apache.ctakes.core.pipeline.PipeBitInfo;
+import org.apache.log4j.Logger;
+import org.apache.uima.UimaContext;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.resource.ResourceInitializationException;
+
+import java.io.IOException;
+
+/**
+ * @author DJ , chip-nlp
+ * @since {2/2/2023}
+ */
+@PipeBitInfo(
+      name = "PbjPipper",
+      description = "Will pip PBJ based upon user request.",
+      role = PipeBitInfo.Role.SPECIAL
+)
+public class PbjPipper extends PythonRunner {
+
+   static private final Logger LOGGER = Logger.getLogger( "PbjPipper" );
+   // to add a configuration parameter, type "param" and hit tab.
+
+   static public final String PIP_PBJ_PARAM = "PipPbj";
+   static public final String PIP_PBJ_DESC = "pip or do not pip PBJ.  Default is yes.";
+   @ConfigurationParameter(
+         name = PIP_PBJ_PARAM,
+         description = PIP_PBJ_DESC,
+         mandatory = false,
+         defaultValue = "yes"
+   )
+   private String _pipPbj;
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void initialize( final UimaContext context ) throws ResourceInitializationException {
+      super.initialize( context );
+   }
+
+   /**
+    * Does nothing.
+    * {@inheritDoc}
+    */
+   @Override
+   public void process( final JCas jcas ) throws AnalysisEngineProcessException {
+   }
+
+   private boolean doPip() {
+      return _pipPbj.isEmpty()
+             || _pipPbj.equalsIgnoreCase( "yes" )
+             || _pipPbj.equalsIgnoreCase( "true" );
+   }
+
+   protected boolean isCommandMandatory() {
+      return false;
+   }
+
+   /**
+    *
+    * @return false as we only want to do this on initialization.
+    */
+   protected boolean processPerDoc() {
+      return false;
+   }
+
+   /**
+    *
+    * @return the pip command to install PBJ.
+    */
+   protected String getCommand() {
+      return "-m pip install resources/org/apache/ctakes/pbj/ctakes_pbj_py/";
+   }
+
+   /**
+    *
+    * @return true
+    */
+   protected boolean shouldWait() {
+      return true;
+   }
+
+   /**
+    * Only run if _pipPbj is yes.
+    * @throws IOException -
+    */
+   protected void runCommand() throws IOException {
+      if ( doPip() ) {
+         LOGGER.info( "Since ctakes-pbj is pip installed from source, pip will always perform an install." );
+         LOGGER.info( "To turn off the pip use \"set " + PIP_PBJ_PARAM + "=no\" in your piper file" );
+         LOGGER.info( " or add \"--pipPbj no\" to your command line." );
+         super.runCommand();
+      }
+   }
+
+
+}
diff --git a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjSender.java b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjSender.java
index 9ef7882..c4deb5a 100644
--- a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjSender.java
+++ b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/ae/PbjSender.java
@@ -426,7 +426,9 @@ public class PbjSender extends JCasAnnotator_ImplBase {
          try {
             return new Socket( host, port );
          } catch ( ConnectException cE ) {
-            LOGGER.error( "Cannot connect to Artemis.  It is possible that Artemis is not running." );
+            LOGGER.error( "Cannot connect to Artemis.  It is possible that Artemis is not running on " + host + "." );
+            LOGGER.error( "Cannot connect to Artemis.  It is possible that port " + port + " is in use." );
+            LOGGER.error( "Please check the Artemis log file, in the output directory by default." );
             throw cE;
          }
       }
diff --git a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/util/ArtemisController.java b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/util/ArtemisController.java
index 793421e..aad0b73 100644
--- a/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/util/ArtemisController.java
+++ b/ctakes-pbj/src/main/java/org/apache/ctakes/pbj/util/ArtemisController.java
@@ -35,16 +35,6 @@ abstract public class ArtemisController extends PausableFileLoggerAE {
     )
     protected String _artemisRoot;
 
-    static public final String WAIT_PARAM = "Wait";
-    static public final String WAIT_DESC = "Wait for the launched command to finish.  Default is no.";
-    @ConfigurationParameter(
-          name = WAIT_PARAM,
-          description = WAIT_DESC,
-          defaultValue = "no",
-          mandatory = false
-    )
-    protected String _wait;
-
     /**
      *
      * @return a suffix for the default log file.
diff --git a/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/README.md b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/README.md
new file mode 100644
index 0000000..0cc4639
--- /dev/null
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/README.md
@@ -0,0 +1,138 @@
+# cTAKES Installation Instructions:
+
+### Windows
+-install tortoiseSVN https://tortoisesvn.net/downloads.html  <br/>
+-Make sure to check "command line client tools" when downloading tortoiseSVN<br/>
+-Once tortoiseSVN is downloaded, open IntelliJ settings, go to the Version control tab on the left hand side. Select the subversion tab, then in the "path to Subversion executable" field fill in : `C:\Program Files\TortoiseSVN\bin\svn.exe` <br/>
+-Download ctakes project using the `get from VCS` button on the "Welcome to IntelliJ" page.
+-Select the svn option from the Version Control dropdown and add https://svn.apache.org/repos/asf/ctakes/trunk/ then checkout<br/> 
+-Select the 1.8 working format of cTakes <br/>
+-Go back to the "Welcome to IntelliJ" page and use the `get from VCS` button again, this time we want to use git. <br/>
+-Copy this link "https://github.com/Johnsd11/ctakes-pbj-v-1.0" and then save the repo in cTakes under the folder "ctakes-pbj" <br/>
+
+
+### Mac and Linux
+-Install Subversion using homebrew then type the command `brew install subversion`(for mac and linux) <br/>
+-Download ctakes project using the `get from VCS` button on the "Welcome to IntelliJ" page.
+-Select the svn option from the Version Control dropdown and add https://svn.apache.org/repos/asf/ctakes/trunk/ then checkout<br/> 
+-Select the 1.8 working format of cTakes <br/>
+-Go back to the "Welcome to IntelliJ" page and use the `get from VCS` button again, this time we want to use git. <br/>
+-Copy this link "https://github.com/Johnsd11/Ctakes_PBJ" and then save the repo in cTakes under the folder "ctakes-pbj" <br/>
+
+
+### Windows
+-install maven using a package manager: chocolatey<br/>
+https://www.how2shout.com/how-to/download-and-install-maven-on-windows-10-or-11-via-command-line.html<br/>
+
+
+### Mac and Linux
+-install maven using brew : `brew install maven` <br/>
+
+---
+
+-Search for and open `pom.xml` for ctakes trunk<br/>
+    - Once in the file scroll down until you come across the `<modules>` list<br/>
+    - add this line `<module>ctakes-pbj</module>` anywhere on the list<br/>
+    - Next look for the `<dependency>` list<br/>
+    - add these lines <br/>
+    `<dependency>` <br/>
+         `<groupId>org.apache.ctakes</groupId>`<br/> 
+         `<artifactId>ctakes-pbj</artifactId>`<br/>
+         `<version>${project.version}</version>`<br/>
+    `</dependency>`<br/>
+-Next open the maven tab on the top right of the intellij window, click Apache cTAKES, Lifecycle, install<br/>
+-After this step, the ctakes-pbj directory will appear to have a blue square on it in the left hand side of IntelliJ that displays project structure.
+
+
+
+### Configurations
+-add python plugin from the IntelliJ plugins store <br/>
+-Set Project SDK: corretto-1.8<br/>
+-Set Project language level: SDK default (8)<br/>
+-install the latest version of java<br/>
+-open Project Structure, navigate to modules tab on the left side, find ctakes-pbj, click on it and then press the plus sign and add python 3.8 to it<br/>
+-**IMPORTANT:** You need to make sure that you follow the step above first before you mark the python and java directories as source roots. <br/>
+-Make sure to mark the ctakes-pbj/src/main/python and ctakes-pbj/src/main/java directories as a source roots <br/>
+  
+
+ # Artemis Instructions For making a Broker:
+-First download ActiveMQ Artemis here: https://activemq.apache.org/components/artemis/download/<br/>
+-Naviagate to the downloaded apache-artemis folder in your command line<br/>
+-from there cd into bin, then while in bin, type "./artemis create mybroker" for MAC or for windows "artemis create mybroker"<br/>
+-This will prompt a Username and Password which can be anything you want<br/>
+-It will also prompt something called `--allow-anonymous`, Press `Y` <br/>
+-From here you can now cd into mybroker/bin<br/>
+-Once you are in bin again you can run "./artemis run" for MAC or "artemis run" for windows to start the broker<br/>
+-Here are more directions if you need more help or clarification<br/>
+-https://activemq.apache.org/components/artemis/documentation/1.0.0/running-server.html<br/>
+  
+# Running an Example
+-You can start running an example by creating an application configuration<br/>
+-You can call it whatever you want, we called it "StartAllExample"<br/>
+-Copy down the information you see in the picture below <br/>
+![step3](https://user-images.githubusercontent.com/34665038/181270724-c1dbc854-397a-4b1f-b5db-e194adf074d5.png)<br/>
+-p "org/apache/ctakes/pbj/pipeline/StartAllExample" <br/>
+-i "org/apache/ctakes/examples/notes/annotated" <br/>
+-a "[Destination of your Artemis Broker]" <br/>
+-d "[Destinaiton of your python.exe]" <br/>
+![step1](https://user-images.githubusercontent.com/34665038/181271047-cf112a93-0d8c-4734-aa21-1281377e6762.png)<br/>
+
+## End-to-end PBJ Examples
+### Temporal Example
+- You first need to get the API side up and running. To do this you need to follow the steps listed [here.](https://github.com/Machine-Learning-for-Medical-Language/cnlp_transformers)
+- Once that is running you need to then create this configuration for StartTemporalExample.piper file.<br/>
+-p<br/>
+org/apache/ctakes/pbj/pipeline/StartTemporalExample<br/>
+-i<br/>
+(input)<br/>
+-a<br/>
+(folder where your Artemis broker is)<br/>
+-d<br/>
+(enviroment) <br/>
+-o<br/>
+(output)<br/>
+--key<br/>
+(UMLS key)<br/>
+- You should now be able to run that piper file while the API side is running. You can look at the output of running the piper file in "temporal_py.log" as well
+as the output file that you put into the configuration.<br/>
+
+### Negation Example
+- You first need to get the API side up and running. To do this you need to follow the steps listed [here.](https://github.com/Machine-Learning-for-Medical-Language/cnlp_transformers)
+- Once that is running you need to then create this configuration for StartNegationExample.piper file.<br/>
+-p<br/>
+org/apache/ctakes/pbj/pipeline/StartNegationExample<br/>
+-i<br/>
+(input)<br/>
+-a<br/>
+(folder where your Artemis broker is)<br/>
+-d<br/>
+(enviroment) <br/>
+-o<br/>
+(output)<br/>
+--key<br/>
+(UMLS key)<br/>
+- You should now be able to run that piper file while the API side is running. You can look at the output of running the piper file in "negation_py.log" as well
+as the output file that you put into the configuration.<br/>
+
+### DTR Example
+- You first need to get the API side up and running. To do this you need to follow the steps listed [here.](https://github.com/Machine-Learning-for-Medical-Language/cnlp_transformers)
+- Once that is running you need to then create this configuration for StartDtrExample.piper file.<br/>
+-p<br/>
+org/apache/ctakes/pbj/pipeline/StartDtrExample<br/>
+-i<br/>
+(input)<br/>
+-a<br/>
+(folder where your Artemis broker is)<br/>
+-d<br/>
+(enviroment) <br/>
+-o<br/>
+(output)<br/>
+--key<br/>
+(UMLS key)<br/>
+- You should now be able to run that piper file while the API side is running. You can look at the output of running the piper file in "dtr_py.log" as well
+as the output file that you put into the configuration.<br/>
+
+  
+  
+
+    
diff --git a/ctakes-pbj/pyproject.toml b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/pyproject.toml
similarity index 100%
rename from ctakes-pbj/pyproject.toml
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/pyproject.toml
diff --git a/ctakes-pbj/setup.cfg b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/setup.cfg
similarity index 89%
rename from ctakes-pbj/setup.cfg
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/setup.cfg
index 59459da..3f5d3bc 100644
--- a/ctakes-pbj/setup.cfg
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
-name = ctakes_pbj
-version = 5.0
+name = ctakes-pbj
+version = 5.0.0
 author = Apache cTAKES
 author_email = dev@ctakes.apache.org
 description = Apache cTAKES Python Bridge to Java
@@ -17,7 +17,7 @@ classifiers =
 
 [options]
 package_dir=
-    = src/main/python
+    = src
 packages = find:
 python_requires = >=3.7, <3.9
 install_requires =
@@ -25,4 +25,4 @@ install_requires =
     stomp.py~=8.0.0
 
 [options.packages.find]
-where = src/main/python
+where = src
diff --git a/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/setup.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/setup.py
new file mode 100644
index 0000000..081cb9f
--- /dev/null
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/setup.py
@@ -0,0 +1,3 @@
+from distutils.core import setup
+from setuptools import find_packages
+setup(name='ctakes_pbj', version='5.0.0', packages=find_packages())
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/__init__.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pipeline/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pipeline/__init__.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/component/cas_annotator.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/cas_annotator.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/component/cas_annotator.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/cas_annotator.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/component/pbj_receiver.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/pbj_receiver.py
similarity index 98%
rename from ctakes-pbj/src/main/python/ctakes_pbj/component/pbj_receiver.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/pbj_receiver.py
index a93c8f9..3a53f44 100644
--- a/ctakes-pbj/src/main/python/ctakes_pbj/component/pbj_receiver.py
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/pbj_receiver.py
@@ -3,7 +3,8 @@ from threading import Event
 import stomp
 from ctakes_pbj.type_system.type_system_loader import *
 from ctakes_pbj.pipeline.pbj_pipeline import STOP_MESSAGE
-from ctakes_pbj import arg_parser
+from ctakes_pbj.pbj_tools import arg_parser
+
 args = arg_parser.get_args()
 
 exit_event = Event()
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/component/pbj_sender.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/pbj_sender.py
similarity index 90%
rename from ctakes-pbj/src/main/python/ctakes_pbj/component/pbj_sender.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/pbj_sender.py
index 6092b1a..e7d40a9 100644
--- a/ctakes-pbj/src/main/python/ctakes_pbj/component/pbj_sender.py
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/component/pbj_sender.py
@@ -1,7 +1,8 @@
 import stomp
 from ctakes_pbj.component import cas_annotator
 from ctakes_pbj.pipeline.pbj_pipeline import STOP_MESSAGE
-from ctakes_pbj import arg_parser
+from ctakes_pbj.pbj_tools import arg_parser
+
 args = arg_parser.get_args()
 
 
@@ -17,6 +18,7 @@ class PBJSender(cas_annotator.CasAnnotator):
         self.username = username
 
     def process(self, cas):
+        print("Sending processed information to " + self.target_queue + " ...")
         xmi = cas.to_xmi()
         conn = stomp.Connection([(self.target_host, self.target_port)])
         conn.connect(self.username, self.password, wait=True)
@@ -31,6 +33,7 @@ class PBJSender(cas_annotator.CasAnnotator):
         conn.send(self.target_queue, text)
 
     def send_stop(self):
+        print("Sending Stop code to " + self.target_queue + " ...")
         conn = stomp.Connection([(self.target_host, self.target_port)])
         conn.connect(self.username, self.password, wait=True)
         conn.send(self.target_queue, STOP_MESSAGE)
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/scripts/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/scripts/__init__.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/examples/sentence_printer.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/sentence_printer.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/examples/sentence_printer.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/sentence_printer.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/examples/sentence_printer_pipeline.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/sentence_printer_pipeline.py
similarity index 81%
rename from ctakes-pbj/src/main/python/ctakes_pbj/examples/sentence_printer_pipeline.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/sentence_printer_pipeline.py
index 29e1b36..134c268 100644
--- a/ctakes-pbj/src/main/python/ctakes_pbj/examples/sentence_printer_pipeline.py
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/sentence_printer_pipeline.py
@@ -5,8 +5,8 @@
 import warnings
 
 
-from ctakes_pbj.component.pbj_receiver import *
-from ctakes_pbj.examples.sentence_printer import *
+from ctakes_pbj.component.pbj_receiver import start_receiver
+from ctakes_pbj.examples.sentence_printer import SentencePrinter
 from ctakes_pbj.component.pbj_sender import PBJSender
 from ctakes_pbj.pipeline.pbj_pipeline import PBJPipeline
 
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/examples/word_finder.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/word_finder.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/examples/word_finder.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/word_finder.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/examples/word_finder_pipeline.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/word_finder_pipeline.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/examples/word_finder_pipeline.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/examples/word_finder_pipeline.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/type_system/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/type_system/__init__.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/arg_parser.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/arg_parser.py
similarity index 87%
rename from ctakes-pbj/src/main/python/ctakes_pbj/arg_parser.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/arg_parser.py
index 9b9ab7e..ea84ef7 100644
--- a/ctakes-pbj/src/main/python/ctakes_pbj/arg_parser.py
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/arg_parser.py
@@ -3,6 +3,7 @@ DEFAULT_HOST = 'localhost'
 DEFAULT_PORT = 61616
 DEFAULT_USER = 'guest'
 DEFAULT_PASS = 'guest'
+DEFAULT_OUT_DIR = 'pbj_output/'
 
 
 def get_args():
@@ -17,6 +18,7 @@ def get_args():
     parser.add_argument('-pn', '--port_name', default=DEFAULT_PORT)
     parser.add_argument('-u', '--username', default=DEFAULT_USER)
     parser.add_argument('-p', '--password', default=DEFAULT_PASS)
+    parser.add_argument('-o', '--output_dir', default=DEFAULT_OUT_DIR)
 
     parser.parse_args()
     args = parser.parse_args()
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/create_relation.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/create_relation.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/create_relation.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/create_relation.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/create_type.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/create_type.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/create_type.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/create_type.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/event_creator.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/event_creator.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/event_creator.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/event_creator.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/get_common_types.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/get_common_types.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/get_common_types.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/get_common_types.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/helper_functions.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/helper_functions.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/helper_functions.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/helper_functions.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/token_tools.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/token_tools.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pbj_tools/token_tools.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pbj_tools/token_tools.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pipeline/__init__.py
similarity index 100%
copy from ctakes-pbj/src/main/python/ctakes_pbj/__init__.py
copy to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pipeline/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/pipeline/pbj_pipeline.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pipeline/pbj_pipeline.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/pipeline/pbj_pipeline.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/pipeline/pbj_pipeline.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/scripts/__init__.py
similarity index 100%
copy from ctakes-pbj/src/main/python/ctakes_pbj/__init__.py
copy to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/scripts/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/scripts/get_typesystems.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/scripts/get_typesystems.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/scripts/get_typesystems.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/scripts/get_typesystems.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/__init__.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/__init__.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/__init__.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/__init__.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/type_system/ctakes_const.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/ctakes_const.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/type_system/ctakes_const.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/ctakes_const.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/type_system/ctakes_types.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/ctakes_types.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/type_system/ctakes_types.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/ctakes_types.py
diff --git a/ctakes-pbj/src/main/python/ctakes_pbj/type_system/type_system_loader.py b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/type_system_loader.py
similarity index 100%
rename from ctakes-pbj/src/main/python/ctakes_pbj/type_system/type_system_loader.py
rename to ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/ctakes_pbj_py/src/ctakes_pbj/type_system/type_system_loader.py
diff --git a/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStarter.piper b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStarter.piper
index c179081..20591f5 100644
--- a/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStarter.piper
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStarter.piper
@@ -6,13 +6,16 @@
 #  This piper will start the Apache Artemis broker pointed to by the -a parameter on the command line.
 #  It will pause for 5 seconds to allow artemis to fully launch.
 #
-#  This piper will then pip the python package requirements for ctakes-pbj in an environment pointed to by the -d parameter on the command line.
+#  This piper will then pip the python package requirements for ctakes-pbj
+#  in an environment pointed to by the -d parameter on the command line.
 #
 
 // Set the command line parameter -a to accept the directory of the Artemis broker.
 cli ArtemisBroker=a
-// Set the command line parameter -d to accept the directory of the Python environment.
-cli CommandDir=d
+// Set the command line parameter -v to accept the directory of the Python environment.
+cli VirtualEnv=v
+// Set the command line parameter --pipPbj to yes or no.
+cli PipPbj=pipPbj
 
 // Write nice big banners when ctakes starts and finishes.
 set WriteBanner=yes
@@ -30,9 +33,8 @@ add ArtemisStarter Pause=5
 //
 // pip the dependency packages in case your environment doesn't have them or needs an update.
 //
-//add CommandRunner Command="python -m pip install ctakes-pbj" Wait=yes
-add CommandRunner Command="python -m pip install -e ctakes-pbj" Wait=yes
-
+//add PythonRunner Command="-m pip install resources/org/apache/ctakes/pbj/ctakes_pbj_py/" Wait=yes
+add PbjPipper
 
 // Add the Finished Logger for some run statistics.
 addLast util.log.FinishedLogger
diff --git a/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStopper.piper b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStopper.piper
index c8ae50e..5cb31c3 100644
--- a/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStopper.piper
+++ b/ctakes-pbj/src/user/resources/org/apache/ctakes/pbj/pipeline/PbjStopper.piper
@@ -5,6 +5,7 @@
 #
 #  This piper will stop the Apache Artemis broker pointed to by the -a parameter on the command line.
 #
+
 // Set the command line parameter -a to accept the directory of the Artemis installation.
 cli ArtemisBroker=a
 
diff --git a/ctakes-relation-extractor/src/main/java/org/apache/ctakes/relationextractor/ae/features/NamedEntityFeaturesExtractor.java b/ctakes-relation-extractor/src/main/java/org/apache/ctakes/relationextractor/ae/features/NamedEntityFeaturesExtractor.java
index 9b542a1..41306ec 100644
--- a/ctakes-relation-extractor/src/main/java/org/apache/ctakes/relationextractor/ae/features/NamedEntityFeaturesExtractor.java
+++ b/ctakes-relation-extractor/src/main/java/org/apache/ctakes/relationextractor/ae/features/NamedEntityFeaturesExtractor.java
@@ -33,6 +33,7 @@ import org.cleartk.ml.feature.extractor.DistanceExtractor;
 import org.cleartk.ml.feature.extractor.FeatureExtractor1;
 import org.cleartk.ml.feature.extractor.NamingExtractor1;
 
+// TODO If this is in use then it should be updated to modern jdk standards
 public class NamedEntityFeaturesExtractor implements RelationFeaturesExtractor<IdentifiedAnnotation,IdentifiedAnnotation> {
 
   private FeatureExtractor1 namedEntityType = new FeatureExtractor1() {
@@ -46,6 +47,7 @@ public class NamedEntityFeaturesExtractor implements RelationFeaturesExtractor<I
   /**
    * All extractors for mention 1, with features named to distinguish them from mention 2
    */
+  @SuppressWarnings( "unchecked" )
   private FeatureExtractor1 mention1FeaturesExtractor = new NamingExtractor1(
       "mention1",
       namedEntityType);
@@ -53,7 +55,8 @@ public class NamedEntityFeaturesExtractor implements RelationFeaturesExtractor<I
   /**
    * All extractors for mention 2, with features named to distinguish them from mention 1
    */
-  private FeatureExtractor1 mention2FeaturesExtractor = new NamingExtractor1(
+  @SuppressWarnings( "unchecked" )
+  final private FeatureExtractor1 mention2FeaturesExtractor = new NamingExtractor1(
       "mention2",
       namedEntityType);
 
@@ -61,7 +64,7 @@ public class NamedEntityFeaturesExtractor implements RelationFeaturesExtractor<I
    * Number of named entities between the two mentions
    */
   @SuppressWarnings("unchecked")
-  private DistanceExtractor nEntityMentionsBetween = new DistanceExtractor(null, EntityMention.class);
+  final private DistanceExtractor nEntityMentionsBetween = new DistanceExtractor(null, EntityMention.class);
 
   @Override
   @SuppressWarnings("unchecked")