/** Split objects into normal and disease components */
  private void splitObjects() {
    normalIds = new HashSet<Long>();
    diseaseIds = new HashSet<Long>();
    RenderablePathway diagram = (RenderablePathway) getRenderable();
    if (pathway == null || diagram.getReactomeDiagramId() == null) return;
    try {
      GKInstance pdInst = adaptor.fetchInstance(diagram.getReactomeDiagramId());
      // Get the disease pathway instance
      List<GKInstance> pathways =
          pdInst.getAttributeValuesList(ReactomeJavaConstants.representedPathway);

      GKInstance diseasePathway = null;
      GKInstance normalPathway = null;
      GKInstance disease = (GKInstance) pathway.getAttributeValue(ReactomeJavaConstants.disease);
      if (disease == null && contains(pathway, pathways)) {
        normalPathway = pathway;
      } else {
        diseasePathway = pathway;
        // There should be a normal pathway contained by a disease pathway
        List<?> subPathways = diseasePathway.getAttributeValuesList(ReactomeJavaConstants.hasEvent);
        for (Object obj : subPathways) {
          GKInstance subPathway = (GKInstance) obj;
          disease = (GKInstance) subPathway.getAttributeValue(ReactomeJavaConstants.disease);
          if (disease == null && contains(subPathway, pathways)) {
            normalPathway = subPathway;
            break;
          }
        }
      }
      if (normalPathway != null) {
        // Get all disease related objects
        Set<GKInstance> normalEvents = InstanceUtilities.grepPathwayEventComponents(normalPathway);
        for (GKInstance inst : normalEvents) normalIds.add(inst.getDBID());
        Set<GKInstance> normalEntities = InstanceUtilities.grepPathwayParticipants(normalPathway);
        for (GKInstance inst : normalEntities) normalIds.add(inst.getDBID());
        if (diseasePathway != null) {
          Set<GKInstance> allEvents = InstanceUtilities.grepPathwayEventComponents(diseasePathway);
          allEvents.removeAll(normalEvents);
          for (GKInstance inst : allEvents) {
            diseaseIds.add(inst.getDBID());
            // Want to make sure disease pathways are connected to objects
            if (inst.getSchemClass().isa(ReactomeJavaConstants.ReactionlikeEvent)) {
              Set<GKInstance> rxtEntities = InstanceUtilities.getReactionParticipants(inst);
              for (GKInstance rxtEntity : rxtEntities) {
                diseaseIds.add(rxtEntity.getDBID());
              }
            }
          }
          //                    Set<GKInstance> allEntities =
          // InstanceUtilities.grepPathwayParticipants(diseasePathway);
          //                    allEntities.removeAll(normalEntities);
          //                    for (GKInstance inst : allEntities)
          //                        diseaseIds.add(inst.getDBID());
        }
      }
      splitComponents();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
 /**
  * Some of disease reactions may not be drawn in the pathway diagram (e.g. LoF or GoF reactions).
  * These reactions should be overlaid onto their normalReaction counterparts, which are encoded by
  * their normalReaction attributes.
  *
  * @param diseaseIds
  */
 private void overlayDiseaseReactions(Set<Long> diseaseIds) {
   // Get the list of all drawing objects for checking
   Map<Long, Renderable> idToObject = new HashMap<Long, Renderable>();
   List<Renderable> components = displayedObject.getComponents();
   if (components == null || components.size() == 0) return;
   for (Renderable r : components) {
     if (r.getReactomeId() == null) continue;
     idToObject.put(r.getReactomeId(), r);
   }
   try {
     normalToDiseaseNode = new HashMap<Node, Node>();
     for (Long diseaseId : diseaseIds) {
       if (idToObject.containsKey(diseaseId)) continue;
       // Have to copy the normal reactions to draw
       GKInstance inst = adaptor.fetchInstance(diseaseId);
       if (inst.getSchemClass().isa(ReactomeJavaConstants.ReactionlikeEvent)) {
         List<GKInstance> normalReactions =
             inst.getAttributeValuesList(ReactomeJavaConstants.normalReaction);
         if (normalReactions != null && normalReactions.size() > 0) {
           for (GKInstance normalRxt : normalReactions) {
             Renderable r = idToObject.get(normalRxt.getDBID());
             if (r instanceof HyperEdge) overlayDiseaseReaction((HyperEdge) r, inst);
           }
         }
       }
     }
     return;
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
 /**
  * Map mutated nodes in a disease reaction to displayed nodes in a normal reaction. The mapping is
  * based on sharing of referenceEntity. This may not be reliable!
  *
  * @param diseaseReaction
  * @param nodes
  * @throws InvalidAttributeException
  * @throws Exception @TODO: add a new attribute normalEntity in the PhysicalEntity class.
  */
 private Map<Node, GKInstance> mapMutatedToNormalNodes(
     GKInstance diseaseReaction,
     HyperEdge normalReaction,
     List<Node> nodes,
     Set<GKInstance> lofInstances)
     throws InvalidAttributeException, Exception {
   List<GKInstance> efs =
       diseaseReaction.getAttributeValuesList(ReactomeJavaConstants.entityFunctionalStatus);
   // Map mutated entities to normal entities via ReferenceGeneProduct
   Map<Node, GKInstance> normalToDiseaseEntity = new HashMap<Node, GKInstance>();
   if (efs == null) return normalToDiseaseEntity;
   for (GKInstance ef : efs) {
     GKInstance pe = (GKInstance) ef.getAttributeValue(ReactomeJavaConstants.physicalEntity);
     if (pe != null) {
       Set<GKInstance> refEntities = getReferenceEntity(pe);
       // want to find the matched node
       for (Node node : nodes) {
         if (node.getReactomeId() == null) continue;
         GKInstance nodeInst = adaptor.fetchInstance(node.getReactomeId());
         Set<GKInstance> nodeRefEntities = getReferenceEntity(nodeInst);
         nodeRefEntities.retainAll(refEntities);
         if (nodeRefEntities.size() > 0) {
           normalToDiseaseEntity.put(node, pe);
           if (isLOFEntity(ef)) {
             lofInstances.add(pe);
           }
           break;
         }
       }
     }
   }
   // TODO: May have to consider stoichiometries too!!!
   // In gain of functions, some inputs or outputs may not be used by normal reactions.
   // This method will do its best to map these reaction participants
   Collection<GKInstance> mapped = normalToDiseaseEntity.values();
   // First check inputs
   List<GKInstance> diseaseInputs =
       diseaseReaction.getAttributeValuesList(ReactomeJavaConstants.input);
   List<Node> normalNodes = normalReaction.getInputNodes();
   randomlyMapDiseaseNodesToNormalNodes(normalToDiseaseEntity, mapped, diseaseInputs, normalNodes);
   // Check outputs
   List<GKInstance> diseaseOutputs =
       diseaseReaction.getAttributeValuesList(ReactomeJavaConstants.output);
   normalNodes = normalReaction.getOutputNodes();
   randomlyMapDiseaseNodesToNormalNodes(
       normalToDiseaseEntity, mapped, diseaseOutputs, normalNodes);
   // Check helpers
   GKInstance ca =
       (GKInstance) diseaseReaction.getAttributeValue(ReactomeJavaConstants.catalystActivity);
   if (ca != null) {
     List<GKInstance> catalysts = ca.getAttributeValuesList(ReactomeJavaConstants.physicalEntity);
     normalNodes = normalReaction.getHelperNodes();
     randomlyMapDiseaseNodesToNormalNodes(normalToDiseaseEntity, mapped, catalysts, normalNodes);
   }
   return normalToDiseaseEntity;
 }
 private void checkLossOfFunctionNodes() {
   try {
     lofNodes = new ArrayList<Node>();
     List<Renderable> components = displayedObject.getComponents();
     if (components == null || components.size() == 0) return;
     for (Renderable r : components) {
       if (r instanceof Node || r.getReactomeId() == null) continue;
       if (!diseaseIds.contains(r.getReactomeId())) continue;
       GKInstance inst = adaptor.fetchInstance(r.getReactomeId());
       if (!inst.getSchemClass().isa(ReactomeJavaConstants.ReactionlikeEvent)
           || !inst.getSchemClass().isValidAttribute(ReactomeJavaConstants.entityFunctionalStatus))
         continue;
       List<GKInstance> efs =
           inst.getAttributeValuesList(ReactomeJavaConstants.entityFunctionalStatus);
       Set<GKInstance> lofPEs = new HashSet<GKInstance>();
       for (GKInstance ef : efs) {
         GKInstance pe = (GKInstance) ef.getAttributeValue(ReactomeJavaConstants.physicalEntity);
         if (isLOFEntity(ef)) lofPEs.add(pe);
       }
       List<Node> nodes = ((HyperEdge) r).getConnectedNodes();
       for (Node node : nodes) {
         if (node.getReactomeId() == null) continue;
         GKInstance nodeInst = adaptor.fetchInstance(node.getReactomeId());
         Set<GKInstance> nodeRefEntities = getReferenceEntity(nodeInst);
         for (GKInstance lofPE : lofPEs) {
           Set<GKInstance> lofRefEntities = getReferenceEntity(lofPE);
           lofRefEntities.retainAll(nodeRefEntities);
           if (lofRefEntities.size() > 0) {
             // A LOF node
             lofNodes.add(node);
             break;
           }
         }
       }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
 }