Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package com.velox.sloan.cmo.workflows.workflows;

import com.velox.api.datarecord.*;
import com.velox.api.plugin.PluginResult;
import com.velox.api.workflow.ActiveTask;
import com.velox.sapioutils.server.plugin.DefaultGenericPlugin;
import com.velox.sapioutils.shared.enums.PluginOrder;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.*;

/**
* Plugin to populate fields for control samples.
*
* This plugin performs three main steps:
* 1. Reads species and recipe values from non-control samples
* 2. Populates control samples with the same species and recipe values
* 3. Links all control samples to a constant dummy request record
*
* The plugin identifies controls using the "IsControl" boolean field in Sample records.
* Controls inherit the species and recipe from regular samples in the same workflow,
* ensuring consistency and enabling automated processing.
*
* @author patelo2
*/
public class ControlFieldsPopulator extends DefaultGenericPlugin {

private static final String DUMMY_REQUEST_ID = "07000";

/**
* Constructor - sets plugin execution parameters
*/
public ControlFieldsPopulator() {
setTaskEntry(true);
setOrder(PluginOrder.MIDDLE.getOrder());
}

/**
* Determines whether this plugin should run for the current task.
*
* @return true if plugin should execute, false otherwise
* @throws RemoteException if there's an error accessing task information
*/
@Override
public boolean shouldRun() throws RemoteException {
return activeTask.getStatus() != ActiveTask.COMPLETE &&
activeTask.getTask().getTaskOptions().containsKey("POPULATE CONTROL FIELDS") &&
!activeTask.getTask().getTaskOptions().containsKey("_CONTROL FIELDS POPULATED");
}

/**
* Main plugin execution method.
*
* Executes the three-step control population process:
* 1. Find non-control samples and extract their species/recipe values
* 2. Populate all control samples with the extracted values
* 3. Link all controls to a constant dummy request record
*
* @return PluginResult indicating success or failure
* @throws Exception if any error occurs during execution
*/
public PluginResult run() throws Exception {
try {
List<DataRecord> samples = activeTask.getAttachedDataRecords("Sample", user);

// Step 1: Find species and recipe from non-control samples
String species = "";
String recipe = "";
for (DataRecord sample : samples) {
Object isControl = sample.getValue("IsControl", user);
// Only process non-control samples (ignore IsControl = false samples completely)
if (isControl == null || !(Boolean) isControl) {
species = sample.getStringVal("Species", user);
recipe = sample.getStringVal("Recipe", user);
if (species != null && recipe != null) {
logInfo("Found species: " + species + ", recipe: " + recipe + " from non-control sample");
break;
}
}
}
// Step 2: Populate control samples with species and recipe
for (DataRecord sample : samples) {
Object isControl = sample.getValue("IsControl", user);
if (isControl != null && (Boolean) isControl) {
String sampleId = sample.getStringVal("SampleId", user);
sample.setDataField("Species", species, user);
sample.setDataField("Recipe", recipe, user);
sample.setDataField("RequestId", DUMMY_REQUEST_ID, user);
logInfo("Updated control sample " + sampleId + " with species: " + species + ", recipe: " + recipe);
}
}
// Step 3: Link all control samples to the constant dummy request record
DataRecord dummyRecord = getDummyRecord();
if (dummyRecord != null) {
for (DataRecord sample : samples) {
Object isControl = sample.getValue("IsControl", user);
if (isControl != null && (Boolean) isControl) {
String sampleId = sample.getStringVal("SampleId", user);
dummyRecord.addChild(sample, user);
logInfo("Linked control sample " + sampleId + " to dummy request record");
}
}
} else {
logError("Could not find or create dummy request record");
return new PluginResult(false);
}

// Mark task as completed
activeTask.getTask().getTaskOptions().put("_CONTROL FIELDS POPULATED", "");

} catch (ServerException e) {
String errMsg = String.format("ServerException while populating control fields:\n%s", ExceptionUtils.getStackTrace(e));
clientCallback.displayError(errMsg);
logError(errMsg);
return new PluginResult(false);
}

return new PluginResult(true);
}

/**
* Gets the constant dummy request record for linking controls.
* This method queries for the existing dummy request record using the predefined RequestId.
* The dummy request record should already exist in the system.
*
* @return DataRecord representing the dummy request, or null if not found
*/
private DataRecord getDummyRecord() {
try {
List<DataRecord> dummyRecords = dataRecordManager.queryDataRecords("Request",
"RequestId = '" + DUMMY_REQUEST_ID + "'", user);

if (dummyRecords != null && !dummyRecords.isEmpty()) {
logInfo("Found existing dummy request record with ID: " + DUMMY_REQUEST_ID);
return dummyRecords.get(0);
} else {
logError("No dummy request record found with ID: " + DUMMY_REQUEST_ID + ". Please ensure the record exists in the system.");
return null;
}

} catch (Exception e) {
logError("Error querying for dummy request record: " + e.getMessage());
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.velox.sloan.cmo.workflows.workflows;

import com.velox.api.datarecord.*;
import com.velox.api.plugin.PluginResult;
import com.velox.api.workflow.ActiveTask;
import com.velox.sapio.commons.exemplar.plugin.PluginOrder;
import com.velox.sapioutils.server.plugin.DefaultGenericPlugin;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class CreateSeqReqForControls extends DefaultGenericPlugin {
public CreateSeqReqForControls() {
setTaskEntry(true);
setOrder(PluginOrder.EARLY.getOrder());
}
@Override
public boolean shouldRun() throws RemoteException {
return activeTask.getStatus() != ActiveTask.COMPLETE && activeTask.getTask().getTaskOptions().containsKey("CREATE SEQ REQUIREMENTS FOR CONTROLS")
&& !activeTask.getTask().getTaskOptions().containsKey("_CONTROLS SEQ REQUIREMENTS CREATED");
}

public PluginResult run() throws Exception {
try {
List<DataRecord> coverageReqRefs = this.dataRecordManager.queryDataRecords("ApplicationReadCoverageRef",
"ReferenceOnly != 1 AND isControl = 1 ", this.user);
List<DataRecord> samples = activeTask.getAttachedDataRecords("Sample", user);
List<DataRecord> seqReuirements = new LinkedList<>();
for (DataRecord sample : samples) {
boolean isControl = sample.getBooleanVal("IsControl", user);
if (isControl) {
Map<String, Object> values = new HashMap<>();
String sampleId = sample.getStringVal("SampleId", user);
String sampleName = sample.getStringVal("OtherSampleId", user);
String recipe = sample.getStringVal("Recipe", user);
String species = sample.getStringVal("Species", user);
for (DataRecord ref : coverageReqRefs) {
if (ref.getStringVal("PlatformApplication", user).equalsIgnoreCase(recipe)) {
values.put("SequencingRunType", ref.getStringVal("SequencingRunType", user));
if (species.equalsIgnoreCase("Human")) {
values.put("RequestedReads", ref.getStringVal("MillionReadsHuman", user));
}
else if (species.equalsIgnoreCase("Mouse")) {
values.put("RequestedReads", ref.getStringVal("MillionReadsMouse", user));
}
}
}
values.put("SampleId", sampleId);
values.put("OtherSampleId", sampleName);
DataRecord newSeqReqRecord = dataRecordManager.addDataRecord("SeqRequirement", user);
newSeqReqRecord.setFields(values, user);
sample.addChild(newSeqReqRecord, user);
seqReuirements.add(newSeqReqRecord);
}
}
this.activeTask.addAttachedDataRecords(seqReuirements);

activeTask.getTask().getTaskOptions().put("_CONTROLS SEQ REQUIREMENTS CREATED", "");
} catch (ServerException e) {
String errMsg = String.format("ServerException while setting sequencing requirements for controls:\n%s", ExceptionUtils.getStackTrace(e));
clientCallback.displayError(errMsg);
logError(errMsg);
return new PluginResult(false);
}
return new PluginResult(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public PluginResult run() throws Exception {
Map<String, Object> values = new HashMap<>();
String sampleId = sample.getStringVal("SampleId", user);
String sampleName = sample.getStringVal("OtherSampleId", user);
String otherSampleId = sample.getStringVal("OtherSampleId", user);
String tumorOrNormal = sample.getStringVal("TumorOrNormal", user);
values.put("SampleId", sampleId);
values.put("SequencingRunType","PE100");
Expand All @@ -54,7 +53,7 @@ public PluginResult run() throws Exception {

activeTask.getTask().getTaskOptions().put("_SEQ REQUIREMENTS CREATED", "");
} catch (ServerException e) {
String errMsg = String.format("ServerException while splitting SmartSeq samples:\n%s", ExceptionUtils.getStackTrace(e));
String errMsg = String.format("ServerException while setting sequencing requirements for SMARTSeq samples:\n%s", ExceptionUtils.getStackTrace(e));
clientCallback.displayError(errMsg);
logError(errMsg);
return new PluginResult(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,12 @@ public PluginResult run() throws RemoteException, com.velox.api.util.ServerExcep
}
}
this.activeTask.removeTaskAttachment(sample.getRecordId());
logInfo("Removed the attached sample!!");
this.activeTask.addAttachedDataRecords(toGetAttached);
logInfo("Attached new splitted samples");
sample.setDataField("ExemplarSampleStatus", "Completed - Smart-Seq cDNA Preparation", user);
logInfo("Original sample status updated to: Completed - Smart-Seq cDNA Preparation");
activeWorkflow.getNext(activeTask).addAttachedDataRecords(toGetAttached);
logInfo("Add new attachments to the next step!");
//this.activeTask.removeTaskAttachment(sample.getRecordId());

}


activeTask.getTask().getTaskOptions().put("_SMARTSEQ SAMPLE SPLITTED", "");
logInfo("Task option updated!");

} catch (NotFound | InvalidValue e) {
String errMsg = String.format("Not Found or Invalid Value exception while splitting SmartSeq samples:\n%s", ExceptionUtils.getStackTrace(e));
Expand All @@ -187,7 +179,6 @@ public PluginResult run() throws RemoteException, com.velox.api.util.ServerExcep
} catch (AlreadyExists e) {
throw new RuntimeException(e);
}
logInfo("Right before returning true for plugin result!");
return new PluginResult(true);
}
}