diff --git a/QoRTs-vignette.pdf b/QoRTs-vignette.pdf
index ee35a25..ab5a89c 100644
Binary files a/QoRTs-vignette.pdf and b/QoRTs-vignette.pdf differ
diff --git a/QoRTs.jar b/QoRTs.jar
index 646480f..c93bf72 100644
Binary files a/QoRTs.jar and b/QoRTs.jar differ
diff --git a/QoRTs_1.2.42.tar.gz b/QoRTs_1.2.42.tar.gz
new file mode 100644
index 0000000..fe096d4
Binary files /dev/null and b/QoRTs_1.2.42.tar.gz differ
diff --git a/README.md b/README.md
index 5c557e9..1d01656 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# QoRTs v1.2.37
-(Compiled Mon May  1 14:23:33 EDT 2017)
+# QoRTs v1.2.42
+(Compiled Fri Jun  2 12:23:55 EDT 2017)
 
 The [QoRTs software package](http://hartleys.github.io/QoRTs/) is a fast, efficient, and portable 
 multifunction toolkit designed to assist in
diff --git a/example-walkthrough.pdf b/example-walkthrough.pdf
index f432f9c..08bf239 100644
Binary files a/example-walkthrough.pdf and b/example-walkthrough.pdf differ
diff --git a/src/HartleyUtils/src/main/scala/internalUtils/genomicAnnoUtils.scala b/src/HartleyUtils/src/main/scala/internalUtils/genomicAnnoUtils.scala
index a578be0..93ca039 100644
--- a/src/HartleyUtils/src/main/scala/internalUtils/genomicAnnoUtils.scala
+++ b/src/HartleyUtils/src/main/scala/internalUtils/genomicAnnoUtils.scala
@@ -154,24 +154,27 @@ object genomicAnnoUtils {
   }
   
   class EfficientGenomeSeqContainer_MFA(infile : String) extends EfficientGenomeSeqContainer {
+    //Implementation note: It is important that you never read from remainderIter without first emptying currentIter!
+    // Otherwise scala attempts to store the currentIter values.
+    // This even remains true if there are no external references to the attached currentIter.
     def switchToChrom(chrom : String){
-        var iterPair = remainderIter.span(line => line != (">"+chrom));
-        if(iterPair._2.hasNext){
-          iterPair = iterPair._2.drop(1).span(line => line.charAt(0) != '>');
-        } else {
-          iterPair = internalUtils.fileUtils.getLinesSmartUnzip(infile).span(line =>  line != (">"+chrom));
-          if(iterPair._2.hasNext){
+        report("Switching to Chromosome: " + chrom + " ["+getDateAndTimeString+"] ... ","debug");
+        while(currentIter.hasNext) currentIter.next;
+        var iter = remainderIter.dropWhile(line => line != (">"+chrom));
+        if(! iter.hasNext){
+          iter = internalUtils.fileUtils.getLinesSmartUnzip(infile).dropWhile(line => line != (">"+chrom));
+          if(iter.hasNext){
             reportln("Returning to start of genome FASTA file. NOTE: for optimal performance, sort the FASTA file so that the chromosomes appear in the same order as in the BAM files.","note");
-            iterPair = iterPair._2.drop(1).span(line => line.charAt(0) != '>');
           } else {
             error("FATAL ERROR: Cannot find chromosome \""+chrom+"\" in genome FASTA file!")
           }
         }
-        reportln("Switching to Chromosome: " + chrom,"debug");
+        val iterPair = iter.drop(1).span(line => line.charAt(0) != '>');
         currentIter = iterPair._1.map(_.toUpperCase());
         remainderIter = iterPair._2;
         clearBuffer();
         currChrom = chrom;
+        report("done ["+getDateAndTimeString+"]\n","debug");
     }
     
     var initialReader = internalUtils.fileUtils.getLinesSmartUnzip(infile);
diff --git a/src/HartleyUtils/src/main/scala/runner/runner.scala b/src/HartleyUtils/src/main/scala/runner/runner.scala
index ff0d67d..5626121 100644
--- a/src/HartleyUtils/src/main/scala/runner/runner.scala
+++ b/src/HartleyUtils/src/main/scala/runner/runner.scala
@@ -9,9 +9,9 @@ import internalUtils.commandLineUI._;
 
 object runner {
   
-  final val QORTS_VERSION = "1.2.37"; // REPLACE_THIS_QORTS_VERSION_VARIABLE_WITH_VERSION_NUMBER          (note this exact text is used in a search-and-replace. Do not change it.)
-  final val QORTS_COMPILE_DATE = "Mon May  1 14:23:33 EDT 2017"; // REPLACE_THIS_QORTS_DATE_VARIABLE_WITH_DATE          (note this exact text is used in a search-and-replace. Do not change it.)
-  final val QORTS_COMPILE_TIME : Long = 1493663013; // REPLACE_THIS_QORTS_DATE_VARIABLE_WITH_TIME          (note this exact text is used in a search-and-replace. Do not change it.)
+  final val QORTS_VERSION = "1.2.42"; // REPLACE_THIS_QORTS_VERSION_VARIABLE_WITH_VERSION_NUMBER          (note this exact text is used in a search-and-replace. Do not change it.)
+  final val QORTS_COMPILE_DATE = "Fri Jun  2 12:23:55 EDT 2017"; // REPLACE_THIS_QORTS_DATE_VARIABLE_WITH_DATE          (note this exact text is used in a search-and-replace. Do not change it.)
+  final val QORTS_COMPILE_TIME : Long = 1496420635; // REPLACE_THIS_QORTS_DATE_VARIABLE_WITH_TIME          (note this exact text is used in a search-and-replace. Do not change it.)
 
   final val QORTS_MAJOR_VERSION = QORTS_VERSION.split("\\.")(0);
   final val QORTS_MINOR_VERSION = QORTS_VERSION.split("\\.")(1);
diff --git a/src/QoRTs/DESCRIPTION b/src/QoRTs/DESCRIPTION
index 5b31d63..74d80d8 100644
--- a/src/QoRTs/DESCRIPTION
+++ b/src/QoRTs/DESCRIPTION
@@ -1,6 +1,6 @@
 Package: QoRTs
-Version: 1.2.37
-Date: 2017-05-01
+Version: 1.2.42
+Date: 2017-06-02
 Title: Quality of RNA-seq Tool
 Authors@R: c(person("Stephen Hartley, PhD", "Developer", role = c("aut", "cre"),
                      email = "QoRTs-contact@list.nih.gov"))
diff --git a/src/QoRTs/NAMESPACE b/src/QoRTs/NAMESPACE
index e81089b..5f895bc 100644
--- a/src/QoRTs/NAMESPACE
+++ b/src/QoRTs/NAMESPACE
@@ -16,6 +16,7 @@ export(
  build.plotter.colorByLane,
  build.plotter.colorByGroup,
  build.plotter.basic,
+ build.plotter.advanced,
  
  #Specific Plots:
  makePlot.qual.pair,
diff --git a/src/QoRTs/R/external.plotting.func.R b/src/QoRTs/R/external.plotting.func.R
index ad24c1e..1cf3cce 100644
--- a/src/QoRTs/R/external.plotting.func.R
+++ b/src/QoRTs/R/external.plotting.func.R
@@ -4413,7 +4413,9 @@ makePlot.legend.box <- function(plotter,debugMode = DEFAULTDEBUGMODE, singleEndM
   plotter.error.wrapper(plot.name, plotterFcn = function(){
     plotter.NVC <- plotter;
     plot(0,0,col="transparent",xlim=c(0,1),ylim=c(0,1), axes=F,xlab="",ylab="");
-
+    
+    diff.text <- "Colored/Marked";
+    
     #internal.plot.legend(plotter,"lines","bottomleft");
     #internal.plot.legend(plotter,"points","bottomright");
     if(is.null(plotter$title.annotations[["main.subtitle"]])){
@@ -4459,6 +4461,12 @@ makePlot.legend.box <- function(plotter,debugMode = DEFAULTDEBUGMODE, singleEndM
     } else if(plotter$plot.type == "colorByX"){
       title.text <- paste0("Summary Plots, By ",plotter$title.highlight.name)
       title.cex <- fit.character.vector(title.text);
+    } else if(plotter$plot.type == "highlightByX"){
+      title.text <- paste0("Summary Plots\n",plotter$title.annotations[["highlight.by.title.name"]],"=",plotter$title.annotations[["highlight"]]," Highlighted")
+      title.cex <- fit.character.vector(title.text);
+    } else if(plotter$plot.type == "colorByXhighlightByY"){
+      title.text <- paste0("Summary Plots\n",plotter$title.annotations[["highlight.by.title.name"]],"=",plotter$title.annotations[["highlight"]]," Highlighted\n",diff.text," by ",plotter$title.annotations[["color.by.title.name"]])
+      title.cex <- fit.character.vector(title.text);
     } else {
       title.text <- paste0("Summary Plots, Custom");
       title.cex <- fit.character.vector(title.text);
diff --git a/src/QoRTs/R/internal.plotting.func.R b/src/QoRTs/R/internal.plotting.func.R
index 7f4f46e..ba0ff9a 100644
--- a/src/QoRTs/R/internal.plotting.func.R
+++ b/src/QoRTs/R/internal.plotting.func.R
@@ -2416,14 +2416,16 @@ internal.plot.legend <- function(plotter, legend.type, legend.pos,
   } else if(plotter$plot.type == "colorByLane"){
   } else if(plotter$plot.type == "colorBySample"){ 
   } else if(plotter$plot.type == "colorByX"){ 
+  } else if(plotter$plot.type == "highlightByX"){ 
+
   } else if(plotter$plot.type == "colorByXhighlightByY"){ 
 
   } else if(plotter$plot.type == "summary"){
     #Do nothing. plot nothing.
     return("");
   } else {
-    #Do nothing. Plot nothing.
-    return("");
+    #???
+    #return("");
   }
 
 
@@ -2578,6 +2580,9 @@ internal.get.main.title.fragment <- function(plotter, plot.type){
   if(plotter$plot.type == "colorByGroup") return(paste0("\n",diff.text," by Group"));
   if(plotter$plot.type == "colorBySample") return(paste0("\n",diff.text," by Sample"));
   if(plotter$plot.type == "colorByX") return(paste0("\n",diff.text," by ",plotter$title.highlight.name));
+  if(plotter$plot.type == "highlightByX"){
+    return(paste0("\n",plotter$title.annotations[["highlight.by.title.name"]],"=",plotter$title.annotations[["highlight"]]," Highlighted"));
+  }
   if(plotter$plot.type == "colorByXhighlightByY"){
     #return(paste0("\n",plotter$title.annotations[["highlight"]]," Highlighted, ",diff.text," by ",plotter$title.annotations[["color.by.title.name"]]));
     return(paste0("\n",plotter$title.annotations[["highlight.by.title.name"]],"=",plotter$title.annotations[["highlight"]]," Highlighted, ",diff.text," by ",plotter$title.annotations[["color.by.title.name"]]));
diff --git a/src/QoRTs/R/plot.param.builders.R b/src/QoRTs/R/plot.param.builders.R
index 7f25ef4..2b9ecd6 100644
--- a/src/QoRTs/R/plot.param.builders.R
+++ b/src/QoRTs/R/plot.param.builders.R
@@ -114,6 +114,8 @@ build.plotter.colorBySample <- function(res, plotter.params = list()){
    final.params <- merge.plotting.params(defaultParams,plotter.params);
    compiled.params <- compile.plotting.params(final.params);
    
+   
+   
    return(build.plotter.color( 
                                             res = res, 
                                             compiled.params = compiled.params,
@@ -159,6 +161,108 @@ build.plotter.colorByX <- function(res, color.by.name, color.by.title.name = col
 
 #########################################################
 
+build.plotter.advanced <- function(res, 
+                                   colorBy = NULL,
+                                   color.title = "?",
+                                   highlightBy = NULL, 
+                                   highlight = "CURR", 
+                                   highlightTitle.singular = NULL,
+                                   highlightTitle.plural = highlightTitle.singular,
+                                   outgroup.title = "Other",
+                                   plotter.params = list()){
+  if(is.null(highlightBy) && is.null(colorBy)){
+    return(build.plotter.basic(res=res,plotter.params=plotter.params));
+  } else if(is.null(highlightBy)){
+    base.defaultParams <- QoRTs.default.plotting.params;
+    defaultParams <- merge.plotting.params(base.defaultParams,list(std.lines.alpha = 125));
+    final.params <- merge.plotting.params(defaultParams,plotter.params);
+    compiled.params <- compile.plotting.params(final.params);
+    
+    if(length(colorBy) == nrow(res@decoder) && any(names(colorBy) != res@decoder$unique.ID)){
+        stop("Error: colorBy vector must be named with unique ID's and be in the correct order!");
+    }
+    
+    colorBy <- ifelse(is.na(colorBy),"NA",colorBy);
+    
+    return(build.plotter.color(
+                                            res = res, 
+                                            compiled.params = compiled.params,
+                                            color.by = colorBy, 
+                                            plot.type = "colorByX",
+                                            color.by.title.name = color.title,
+                                            title.annotations = list( 
+                                                             color.by.title.name = color.title)
+                                            ));
+  } else if(is.null(colorBy)){
+    if(is.null(highlightTitle.singular)) highlightTitle.singular <- deparse(substitute(highlightBy));
+    if(is.null(highlightTitle.plural))   highlightTitle.plural <- highlightTitle.singular;
+  
+     if(length(highlightBy) == nrow(res@decoder) && any(names(highlightBy) != res@decoder$unique.ID)){
+        stop("Error: highlightBy vector must be named with unique.ID's and be in the same order as res@decoder$unique.ID");
+     }
+   
+     base.defaultParams <- QoRTs.default.plotting.params;
+     defaultParams <- merge.plotting.params(base.defaultParams,list());
+     final.params <- merge.plotting.params(defaultParams,plotter.params);
+     compiled.params <- compile.plotting.params(final.params);
+   
+     return(build.plotter.highlight(highlight, 
+                                  res = res, 
+                                  compiled.params = compiled.params,
+                                  highlight.by = highlightBy, 
+                                  plot.type = "highlightByX", 
+                                  offset.by = ifelse(highlightBy == highlight,"1","0"), 
+                                  merge.offset.outgroup = TRUE,
+                                    title.annotations = list(highlight=highlight, 
+                                                             highlight.by.name=highlightTitle.plural,
+                                                             highlight.by.title.name = highlightTitle.singular),
+                                  outgroup.name = paste0(outgroup.title),
+                                  highlightTitle.plural = highlightTitle.plural
+                                  ));
+  } else {
+    if(is.null(highlightTitle.singular)) highlightTitle.singular <- deparse(substitute(highlightBy));
+    if(is.null(highlightTitle.plural))   highlightTitle.plural <- highlightTitle.singular;
+  
+    base.defaultParams <- QoRTs.default.plotting.params;
+    defaultParams <- merge.plotting.params(base.defaultParams,list(std.lines.alpha = 125));
+    final.params <- merge.plotting.params(defaultParams,plotter.params);
+    compiled.params <- compile.plotting.params(final.params);
+  
+    if(length(colorBy) == nrow(res@decoder) && any(names(colorBy) != res@decoder$unique.ID)){
+        stop("Error: colorBy vector must be named with unique ID's and be in the correct order!");
+    }
+     if(length(highlightBy) == nrow(res@decoder) && any(names(highlightBy) != res@decoder$unique.ID)){
+        stop("Error: highlightBy vector must be named with unique.ID's and be in the same order as res@decoder$unique.ID");
+     }
+  
+    colorBy     <- ifelse(is.na(colorBy),"NA",colorBy);
+    highlightLogical <- f.na(highlightBy == highlight);
+    highlightBy[!highlightLogical] <- outgroup.title;
+  
+    color.highlighted.by <- colorBy;
+  
+    plotter <-
+    build.plotter.highlight.and.color(curr.highlight = highlight, 
+                                    res=res, 
+                                    compiled.params=compiled.params, 
+                                    highlight.by = highlightBy, 
+                                    color.highlighted.by = color.highlighted.by, 
+                                    title.annotations = list(highlight=highlight, 
+                                                             highlight.by.name=highlightTitle.plural,
+                                                             highlight.by.title.name = highlightTitle.singular, 
+                                                             color.by.title.name = color.title),
+                                    plot.type="colorByXhighlightByY", 
+                                    offset.by = color.highlighted.by, 
+                                    merge.offset.outgroup = TRUE, 
+                                    pch.matched.with.color = TRUE, 
+                                    highlighted.by.name = highlightTitle.plural)
+    return(plotter)
+  }
+}
+
+#########################################################
+#########################################################
+
 build.plotter.colorByVector <- function(res, colorBy, color.by.title.name = "?", plotter.params = list()){
   base.defaultParams <- QoRTs.default.plotting.params;
   defaultParams <- merge.plotting.params(base.defaultParams,list(std.lines.alpha = 125));
@@ -180,6 +284,7 @@ build.plotter.colorByVector <- function(res, colorBy, color.by.title.name = "?",
                                             color.by.title.name = color.by.title.name));
 }
 
+
 build.plotter.colorAndHighlightByVector <- function(res, 
                                                     colorBy, 
                                                     color.by.title.name = "?",
@@ -217,6 +322,7 @@ build.plotter.colorAndHighlightByVector <- function(res,
   return(plotter)
 }
 
+
 build.plotter.colorAndHighlightBySampleVector <- function(res, colorBy, color.by.title.name = "?",
                                                     highlightList,
                                                     plotter.params = list()){
@@ -336,6 +442,131 @@ build.plotter.basic.helper <- function(res, offset.by, compiled.params, plot.typ
 ##################################################################################################################
 ##################################################################################################################
 
+
+build.plotter.advanced.internal <- function(curr.highlight, res, compiled.params, highlight.by, color.highlighted.by, plot.type, offset.by = color.highlighted.by, merge.offset.outgroup = TRUE, pch.matched.with.color = TRUE, highlighted.by.name = "Samples",title.annotations=list()){
+  if(! is.null(check.isValid(res))){
+    #THROW AN ERROR!
+    stop("Error parsing results: ", check.isValid(res));
+  }
+  if(length(highlight.by) != length(color.highlighted.by)) stop("error: length(highlight.by) != length(color.highlighted.by)\n   length(highlight.by) = ",length(highlight.by),", length(color.highlighted.by) = ",length(color.highlighted.by));
+  if(length(highlight.by) != length(res@decoder$unique.ID)) stop("error: length(highlight.by) != length(res@decoder$unique.ID)\n   length(highlight.by) = ",length(highlight.by),", length(res@decoder$unique.ID) = ",length(res@decoder$unique.ID));
+   if(! (curr.highlight %in% highlight.by)){
+      stop("FATAL ERROR! ","Cannot find highlighted element ", curr.highlight," in the highlight list!");
+   }
+  
+  #plotParams <- new("QoRT_Plotter");
+  #plotParams@res <- res;
+  #plotParams@plot.type <- plot.type;
+  title.highlight.name <- curr.highlight;
+  showLegend <- compiled.params@showLegend;
+  nvc.colors <- compiled.params@nvc.colors;
+  nvc.colors.light <- compiled.params@nvc.colors.light;
+  
+  is.highlighted <- highlight.by == curr.highlight;
+  lanebam.ct <- length(highlight.by);
+  hl.by.factor <- color.highlighted.by[is.highlighted ];
+  hl.by.factor.levels <- sort(unique(hl.by.factor));
+  
+  if(length(hl.by.factor.levels) > length(compiled.params@by.colors)) {
+    message("WARNING WARNING WARNING: Too many categories to color! (Max = ",length(compiled.params@by.colors),", curr = ",length(hl.by.factor.levels),") Add more colors? Falling back to a rainbow palette");
+    compiled.params@by.colors <- rainbow(length(hl.by.factor.levels));
+  } 
+  if(pch.matched.with.color){
+    if(length(hl.by.factor.levels) > length(compiled.params@by.pch)){
+      message("WARNING WARNING WARNING: Too many categories to mark distinct with pch! (Max = ",length(compiled.params@by.pch),", curr = ",length(hl.by.factor.levels),") Add more colors? Falling back to a repeating pattern.");
+      compiled.params@by.pch <- rep(compiled.params@by.pch, ceiling( length(hl.by.factor.levels) / length(compiled.params@by.pch)));
+    }
+    legend.points.pch <- compiled.params@by.pch[1:length(hl.by.factor.levels)];
+  } else {
+    legend.points.pch <- rep(compiled.params@highlight.points.pch[1], length(hl.by.factor.levels));
+  }
+
+  legend.params <- data.frame(name = c(hl.by.factor.levels, paste0("Other ",highlighted.by.name)),
+                                         lines.col = c(compiled.params@by.colors[1:length(hl.by.factor.levels)], compiled.params@highlight.color[2]),
+                                         lines.lty = c(rep(compiled.params@highlight.lines.lty[1],length(hl.by.factor.levels)), compiled.params@highlight.lines.lty[2]),
+                                         points.pch = c(legend.points.pch, compiled.params@highlight.points.pch[2]),
+                                         points.col = c(compiled.params@by.colors[1:length(hl.by.factor.levels)], compiled.params@highlight.color[2]),
+                                         stringsAsFactors=F
+  );
+  
+  lines.col <- sapply(1:lanebam.ct, FUN=function(i){
+    if(! is.highlighted[i]){ return(compiled.params@highlight.color[2]);
+    } else {return( legend.params$lines.col[ legend.params$name == color.highlighted.by[i] ] );}
+  });
+  points.col <- sapply(1:lanebam.ct, FUN=function(i){
+    if(! is.highlighted[i]){ return(compiled.params@highlight.color[2]);
+    } else {return( legend.params$points.col[ legend.params$name == color.highlighted.by[i] ] );}
+  });
+
+  if(pch.matched.with.color){
+    #message("!!!");
+    if(length(hl.by.factor.levels) > length(compiled.params@by.pch)) stop("to many categories in by.colors! Add more pch values to compiled.params@by.pch!");
+    points.pch <- sapply(1:lanebam.ct, FUN=function(i){
+      if(! is.highlighted[i]){ return(compiled.params@highlight.points.pch[2]);
+      } else {return( legend.params$points.pch[ legend.params$name == color.highlighted.by[i] ] );}
+    });
+    #message(paste("compiled.params@highlight.points.pch: ",compiled.params@highlight.points.pch,collapse=","));
+    #message(paste("compiled.params@highlight.points.pch: ",compiled.params@highlight.points.pch,collapse=","));
+    #message(paste("points.pch: ",points.pch,collapse=","));
+  } else {
+    points.pch <- ifelse(is.highlighted, compiled.params@highlight.points.pch[1], compiled.params@highlight.points.pch[2])
+  }
+
+
+  
+  if(merge.offset.outgroup){
+    offset.by.vals <- sort(unique(offset.by[is.highlighted]));
+    if( all(offset.by %in% offset.by.vals)){
+      offset.ct <- length(offset.by.vals) ;
+    } else {
+      offset.ct <- length(offset.by.vals) + 1;
+    }
+  } else {
+    offset.by.vals <- sort(unique(offset.by));
+    offset.ct <- length(offset.by.vals) ;
+  }
+  if(offset.ct %% 2 == 0){
+    offsets <- (((1:offset.ct) / (offset.ct)) );
+    offsets <- offsets - ( offsets[ offset.ct / 2  + 1] + offsets[ offset.ct / 2 ]  ) / 2
+  } else {
+    offsets <- (((1:offset.ct) / (offset.ct)) - 0.5  );
+    offsets <- offsets - offsets[ (offset.ct + 1) / 2 ];
+  }
+  
+  lanebam.offset.indices <- sapply(1:lanebam.ct, FUN=function(i){
+    if(any(offset.by.vals == offset.by[i])){
+      which(offset.by.vals == offset.by[i]);
+    } else {
+      offset.ct;
+    }
+  });
+  lanebam.offsets <- offsets[lanebam.offset.indices];
+
+  lanebam.params <- data.frame( plot.priority = ifelse(is.highlighted, 2,1),
+                                           unique.ID = res@decoder$unique.ID,
+                                           lines.col = lines.col,
+                                           points.col = points.col,
+                                           points.pch = points.pch,
+                                           lines.lty = ifelse(is.highlighted, compiled.params@highlight.lines.lty[1], compiled.params@highlight.lines.lty[2]),
+                                           lines.lwd = ifelse(is.highlighted, compiled.params@highlight.lines.lwd[1], compiled.params@highlight.lines.lwd[2]),
+                                           lines.alpha = ifelse(is.highlighted, compiled.params@highlight.lines.alpha[1], compiled.params@highlight.lines.alpha[2]),
+                                           points.alpha = ifelse(is.highlighted, compiled.params@highlight.points.alpha[1], compiled.params@highlight.points.alpha[2]),
+                                           horiz.offsets = lanebam.offsets,
+                                           vert.offsets = lanebam.offsets,
+                                           stringsAsFactors=F
+  );
+  lanebam.params$lines.tcol  <- color2transparent(lanebam.params$lines.col,lanebam.params$lines.alpha);
+  lanebam.params$points.tcol <- color2transparent(lanebam.params$points.col,lanebam.params$points.alpha);
+  
+  plotParams <- generate.plotter(res = res, plot.type = plot.type, title.highlight.name = title.highlight.name, legend.params = legend.params, showLegend = showLegend, nvc.colors = nvc.colors, nvc.colors.light = nvc.colors.light, lanebam.params = lanebam.params,randomize.plot.order=compiled.params@randomize.plot.order,
+                                 title.annotations=c(title.annotations,compiled.params@plot.annotation))
+  return(plotParams);
+}
+
+##################################################################################################################
+##################################################################################################################
+##################################################################################################################
+
 build.plotter.highlight.and.color <- function(curr.highlight, res, compiled.params, highlight.by, color.highlighted.by, plot.type, offset.by = color.highlighted.by, merge.offset.outgroup = TRUE, pch.matched.with.color = TRUE, highlighted.by.name = "Samples",title.annotations=list()){
   if(! is.null(check.isValid(res))){
     #THROW AN ERROR!
@@ -667,7 +898,9 @@ build.plotter.highlight.OLD <- function(curr.highlight, res, compiled.params, hi
 
 
 build.plotter.highlight <- function(curr.highlight, res, 
-                                    title.highlight.name=curr.highlight, compiled.params, highlight.by, plot.type, offset.by, merge.offset.outgroup = TRUE,title.annotations=list()){
+                                    title.highlight.name=curr.highlight, compiled.params, highlight.by, plot.type, offset.by, merge.offset.outgroup = TRUE,title.annotations=list(),
+                                    outgroup.name = "Other",
+                                    highlightTitle.plural = "Samples", highlightTitle.singular = "Sample"){
   if(! is.null(check.isValid(res))){
     #THROW AN ERROR!
     stop("Error parsing results: ", check.isValid(res));
@@ -691,7 +924,7 @@ build.plotter.highlight <- function(curr.highlight, res,
   is.highlighted <- highlight.by %in% curr.highlight;
   lanebam.ct <- length(highlight.by);
   
-  legend.params <- data.frame(name = c(title.highlight.name,"Other Samples"),
+  legend.params <- data.frame(name = c(title.highlight.name,paste0(outgroup.name," ",highlightTitle.plural)),
                                          lines.col = compiled.params@highlight.color,
                                          lines.lty = compiled.params@highlight.lines.lty,
                                          points.pch = compiled.params@highlight.points.pch,
diff --git a/src/QoRTs/R/read.files.R b/src/QoRTs/R/read.files.R
index 4673d0f..ca14525 100644
--- a/src/QoRTs/R/read.files.R
+++ b/src/QoRTs/R/read.files.R
@@ -174,7 +174,7 @@ expandAndCheckDecoder <- function(decoder) {
     subsetDecoder <- decoder[ decoder$sample.ID == samp,];
     if(nrow(subsetDecoder) > 1){
       if(length(unique(subsetDecoder$group.ID)) != 1){
-        stop("Decoder error: sample ",samp," has inconsistent group.ID depending on decoder row: (",paste0(unique,collapse=","),")");
+        stop("Decoder error: sample ",samp," has inconsistent group.ID depending on decoder row: (sample.ID=",samp," found in: ",paste0(unique(subsetDecoder$group.ID),collapse=","),")");
       }
     }
   }
diff --git a/src/QoRTs/man/build.plotter.Rd b/src/QoRTs/man/build.plotter.Rd
index 165989d..fdcf2a3 100644
--- a/src/QoRTs/man/build.plotter.Rd
+++ b/src/QoRTs/man/build.plotter.Rd
@@ -9,6 +9,7 @@
 \alias{build.plotter.colorBySample}
 \alias{build.plotter.basic}
 \alias{build.plotter.colorByX}
+\alias{build.plotter.advanced}
 \alias{QoRTs.default.plotting.params}
 \alias{plotter}
 \title{
@@ -41,11 +42,24 @@
                          color.by.title.name = color.by.name, 
                          plotter.params = list())
 
+  build.plotter.advanced(res, 
+                         colorBy = NULL,
+                         color.title = "?",
+                         highlightBy = NULL, 
+                         highlight = "CURR", 
+                         highlightTitle.singular = NULL,
+                         highlightTitle.plural = highlightTitle.singular,
+                         outgroup.title = "Other",
+                         plotter.params = list())
+
 }
 \arguments{
   \item{res}{
     A \code{QoRT_QC_Results} object, created by \code{\link{read.qc.results.data}}.
   }
+  
+
+  
   \item{curr.sample}{
     A character string. For the sample highlight summary plots,
     this should be the sample.ID of the sample that is to be
@@ -100,6 +114,28 @@
   \item{lane.column.name}{
     The name of the column in the decoder containing the "lane" names.
   }
+  
+  \item{colorBy}{
+    A named character vector. Each unique colorBy string will be assigned a unique color. The names of colorBy must match \code{res@decoder$unique.ID}, and must be in the same order.
+  }
+  \item{color.title}{
+    A character string. This is the title of the colorby category, used in the titles and figure legends.
+  }
+  \item{highlightBy}{
+    A named character vector. Used to determine which replicates to highlight. The names of colorBy must match \code{res@decoder$unique.ID}, and must be in the same order.
+  }
+  \item{highlight}{
+    A character string. Replicates where highlight equals highlightBy will be highlighted.
+  }
+  \item{highlightTitle.singular}{
+    A character string. The singular form of the name of the category highlighted.
+  }
+  \item{highlightTitle.plural}{
+    A character string. The plural form of the name of the category highlighted.
+  }
+  \item{outgroup.title}{
+    A character string. The description of the non-highlighted category. Used in the figure legends.
+  }
 }
 \value{
   A QoRT_Plotter reference object used to create QC summary plots. Depending on which plotter is used, samples/lane-bams can be organized by group, sample, lane, or any arbitrary variable found in the decoder.
@@ -130,6 +166,81 @@ plotter.HSCBL <- build.plotter.highlightSample.colorByLane("SAMP1",
                                                            res);
 makePlot.insert.size(plotter.HSCBL);
 makePlot.legend.over("topright",plotter.HSCBL);
+
+
+#FOR ADVANCED USERS:
+#  With the build.plotter.advanced function, you can
+#  set coloring and highlighting to match anything you
+#  want.
+#  The parameters are a little more complex...
+
+#In order to control color, you must create a named
+#  vector with names equal to the unique.ID's
+#  in the decoder, and in the same order:
+#  (this requirement is purely to prevent mistakes)
+
+#For example: to color each sample differently:
+colorBy <- res@decoder$sample.ID
+names(colorBy) <- res@decoder$unique.ID;
+
+plotter <- build.plotter.advanced(res, colorBy = colorBy);
+makePlot.insert.size(plotter);
+makePlot.legend.over("topright",plotter);
+
+#Now, to highlight a subgroup of the dataset, you
+#  must set the "highlightBy" parameter to a 
+#  named vector with names equal to the decoder 
+#  unique.ID's, and in the same order.
+#  (this requirement is purely to prevent mistakes)
+#Then you must tell the plotter which subgroup
+#  you want to highlight using the "highlight" 
+#  parameter.
+
+#For example, to highlight all lanebams in lane L1:
+highlightBy <- res@decoder$lane.ID
+names(highlightBy) <- res@decoder$unique.ID;
+
+plotter <- build.plotter.advanced(res, 
+                                 highlightBy = highlightBy,
+                                 highlight = "L1");
+makePlot.insert.size(plotter);
+makePlot.legend.over("topright",plotter);
+
+#Other parameters are available to change the title
+# and legends:
+plotter <- build.plotter.advanced(res, 
+                                 highlightBy = highlightBy,
+                                 highlight = "L1",
+                                 highlightTitle.singular = "Lane",
+                                 highlightTitle.plural  = "Lanes",
+                                 outgroup.title = "Other");
+makePlot.insert.size(plotter);
+makePlot.legend.over("topright",plotter);
+
+#You can also color and highlight together.
+#  If you do this, only the "highlighted" group will be
+#  colored, all the others will be colored gray and will be 
+#  drawn in the background. This can be useful for finding
+#  biases that are restricted to a subset of the data.
+
+plotter <- build.plotter.advanced(res, 
+  colorBy = colorBy,
+  highlightBy = highlightBy,
+  highlight = "L1",
+  color.title = "sample",
+  highlightTitle.singular = "Lane",
+  highlightTitle.plural = "Lanes",
+  outgroup.title = "Other"
+);
+makePlot.insert.size(plotter);
+makePlot.legend.over("topright",plotter);
+
+
+#You can make multiplots using a given plotter object by
+# using the "makeMultiPlot.withPlotter" function:
+
+#makeMultiPlot.withPlotter(plotter);
+
 }
 
 \seealso{