Skip to content

Commit 137958d

Browse files
authored
Merge branch 'discvr-21.7' into 21.7_fb_isolate_search
2 parents ecc0035 + c8cc2e3 commit 137958d

File tree

15 files changed

+200
-143
lines changed

15 files changed

+200
-143
lines changed

OpenLdapSync/build.gradle

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
import org.labkey.gradle.util.BuildUtils;
2+
import org.labkey.gradle.util.ExternalDependency
3+
14
dependencies {
2-
external "org.apache.directory.api:api-all:${apacheDirectoryVersion}"
5+
BuildUtils.addExternalDependency(
6+
project,
7+
new ExternalDependency(
8+
"org.apache.directory.api:api-all:${apacheDirectoryVersion}",
9+
'Apache Directory',
10+
'Apache Directory',
11+
'http://directory.apache.org/',
12+
ExternalDependency.APACHE_2_LICENSE_NAME,
13+
ExternalDependency.APACHE_2_LICENSE_URL,
14+
'Used by LDAP Sync'
15+
)
16+
)
317
}

OpenLdapSync/resources/credits/dependencies.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.

OpenLdapSync/resources/credits/jars.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

SequenceAnalysis/src/org/labkey/sequenceanalysis/SequenceAnalysisController.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
import org.labkey.api.util.ExceptionUtil;
119119
import org.labkey.api.util.FileType;
120120
import org.labkey.api.util.FileUtil;
121+
import org.labkey.api.util.HtmlString;
121122
import org.labkey.api.util.NetworkDrive;
122123
import org.labkey.api.util.PageFlowUtil;
123124
import org.labkey.api.util.Pair;
@@ -218,11 +219,17 @@ public SequenceAnalysisController()
218219
public class FastqcReportAction extends SimpleViewAction<FastqcForm>
219220
{
220221
@Override
221-
public ModelAndView getView(FastqcForm form, BindException errors) throws Exception
222+
public void validate(FastqcForm form, BindException errors)
222223
{
223-
if (form.getFilenames() == null && form.getDataIds() == null)
224-
errors.reject("Must provide a filename or Exp data Ids");
224+
if (form.getReadsets() == null && form.getFilenames() == null && form.getDataIds() == null && form.getAnalysisIds() == null)
225+
{
226+
errors.reject(ERROR_MSG, "Must provide a filename or Exp data Ids");
227+
}
228+
}
225229

230+
@Override
231+
public ModelAndView getView(FastqcForm form, BindException errors) throws Exception
232+
{
226233
//resolve files
227234
List<File> files = new ArrayList<>();
228235
Map<File, String> labels = new HashMap<>();
@@ -312,7 +319,7 @@ public ModelAndView getView(FastqcForm form, BindException errors) throws Except
312319
try
313320
{
314321
String html = runner.execute(files, labels);
315-
return new HtmlView("FastQC Report", html);
322+
return new HtmlView("FastQC Report", HtmlString.unsafe(html));
316323
}
317324
catch (FileNotFoundException e)
318325
{
@@ -597,20 +604,20 @@ public void validateCommand(DeleteForm form, Errors errors)
597604
{
598605
if (form.getSchema() == null)
599606
{
600-
errors.reject("No schema provided");
607+
errors.reject(ERROR_MSG, "No schema provided");
601608
return;
602609
}
603610

604611
if (form.getQueryName() == null)
605612
{
606-
errors.reject("No queryName provided");
613+
errors.reject(ERROR_MSG, "No queryName provided");
607614
return;
608615
}
609616

610617
_table = SequenceAnalysisSchema.getInstance().getSchema().getTable(form.getQueryName());
611618
if (_table == null)
612619
{
613-
errors.reject("Unknown table: " + form.getQueryName());
620+
errors.reject(ERROR_MSG, "Unknown table: " + form.getQueryName());
614621
return;
615622
}
616623

@@ -2220,7 +2227,7 @@ public ApiResponse execute(CreateReferenceLibraryForm form, BindException errors
22202227
String[] coordinates = t.split("-");
22212228
if (coordinates.length != 2)
22222229
{
2223-
errors.reject("Inproper interval: [" + t + "]");
2230+
errors.reject(ERROR_MSG, "Inproper interval: [" + t + "]");
22242231
return null;
22252232
}
22262233

@@ -3143,7 +3150,7 @@ public void exec(ResultSet object) throws SQLException
31433150
String wholeSequence = model.getSequence();
31443151
if (wholeSequence == null)
31453152
{
3146-
errors.reject("Unable to find sequence for: " + rowId);
3153+
errors.reject(ERROR_MSG, "Unable to find sequence for: " + rowId);
31473154
return;
31483155
}
31493156

@@ -3152,21 +3159,21 @@ public void exec(ResultSet object) throws SQLException
31523159
String[] coordinates = t.split("-");
31533160
if (coordinates.length != 2)
31543161
{
3155-
errors.reject("Inproper interval: [" + t + "]");
3162+
errors.reject(ERROR_MSG, "Inproper interval: [" + t + "]");
31563163
return;
31573164
}
31583165

31593166
Integer start = StringUtils.trimToNull(coordinates[0]) == null ? null : ConvertHelper.convert(coordinates[0], Integer.class);
31603167
if (wholeSequence.length() < start)
31613168
{
3162-
errors.reject("Start is beyond the length of the sequence. Length: " + wholeSequence.length());
3169+
errors.reject(ERROR_MSG, "Start is beyond the length of the sequence. Length: " + wholeSequence.length());
31633170
return;
31643171
}
31653172

31663173
Integer stop = StringUtils.trimToNull(coordinates[1]) == null ? null : ConvertHelper.convert(coordinates[1], Integer.class);
31673174
if (wholeSequence.length() < stop)
31683175
{
3169-
errors.reject("Stop is beyond the length of the sequence. Length: " + wholeSequence.length());
3176+
errors.reject(ERROR_MSG, "Stop is beyond the length of the sequence. Length: " + wholeSequence.length());
31703177
return;
31713178
}
31723179

@@ -3274,7 +3281,7 @@ public ApiResponse execute(RecreateReferenceLibraryForm form, BindException erro
32743281
{
32753282
if (form.getLibraryIds() == null || form.getLibraryIds().length == 0)
32763283
{
3277-
errors.reject("Must provide a list of reference genomes to re-process");
3284+
errors.reject(ERROR_MSG, "Must provide a list of reference genomes to re-process");
32783285
return null;
32793286
}
32803287

SequenceAnalysis/src/org/labkey/sequenceanalysis/pipeline/ReadsetCreationTask.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,13 @@ private void importReadsets() throws PipelineJobException
174174
getJob().getLogger().info("Starting readset " + r.getName());
175175

176176
boolean readsetExists = r.getReadsetId() != null && r.getReadsetId() > 0;
177-
List<ReadDataImpl> preexistingReadData;
178-
if (readsetExists)
177+
SequenceReadsetImpl existingReadset = readsetExists ? ((SequenceReadsetImpl)SequenceAnalysisService.get().getReadset(r.getReadsetId(), getJob().getUser())) : null;
178+
List<ReadDataImpl> preexistingReadData = readsetExists ? existingReadset.getReadDataImpl() : Collections.emptyList();
179+
boolean readsetExistsWithData = !preexistingReadData.isEmpty();
180+
if (readsetExistsWithData)
179181
{
180-
readsetsToDeactivate.put(r.getReadsetId(), r.getContainer());
181-
preexistingReadData = ((SequenceReadsetImpl)SequenceAnalysisService.get().getReadset(r.getReadsetId(), getJob().getUser())).getReadDataImpl();
182-
}
183-
else
184-
{
185-
preexistingReadData = Collections.emptyList();
182+
getJob().getLogger().info("Readset has existing data: " + r.getName() + ", " + r.getRowId() + " from: " + existingReadset.getContainer());
183+
readsetsToDeactivate.put(r.getReadsetId(), existingReadset.getContainer());
186184
}
187185

188186
SequenceReadsetImpl row;
@@ -438,14 +436,18 @@ private void importReadsets() throws PipelineJobException
438436
List<Map<String, Object>> toUpdate = new ArrayList<>();
439437
List<Map<String, Object>> toUpdateKeys = new ArrayList<>();
440438
readsetsToDeactivate.forEach((rowId, container) -> {
439+
Readset r = SequenceAnalysisService.get().getReadset(rowId, getJob().getUser());
440+
441441
Map<String, Object> row = new CaseInsensitiveHashMap<>();
442442
row.put("rowid", rowId);
443443
row.put("container", container);
444444
row.put("status", "Replaced");
445+
row.put("name", r.getName() + "-Replaced");
445446
toUpdate.add(row);
446447

447448
row = new CaseInsensitiveHashMap<>();
448449
row.put("rowid", rowId);
450+
row.put("container", container);
449451
toUpdateKeys.add(row);
450452
});
451453

SequenceAnalysis/src/org/labkey/sequenceanalysis/run/analysis/NextCladeHandler.java

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public static File runNextClade(File consensusFasta, Logger log, PipelineOutputT
166166
writer.println("HOME=`echo ~/`");
167167

168168
writer.println("DOCKER='" + SequencePipelineService.get().getDockerCommand() + "'");
169-
writer.println("sudo $DOCKER pull neherlab/nextclade");
169+
writer.println("sudo $DOCKER pull nextstrain/nextclade:latest");
170170
writer.println("sudo $DOCKER run --rm=true \\");
171171

172172
if (SequencePipelineService.get().getMaxThreads(log) != null)
@@ -185,8 +185,8 @@ public static File runNextClade(File consensusFasta, Logger log, PipelineOutputT
185185
writer.println("\t-u $UID \\");
186186
writer.println("\t-e USERID=$UID \\");
187187
writer.println("\t-w /work \\");
188-
writer.println("\tneherlab/nextclade \\");
189-
writer.println("\t nextclade --input-fasta '/work/" + consensusFasta.getName() + "' --output-json '/work/" + jsonFile.getName() + "'");
188+
writer.println("\tnextstrain/nextclade:latest \\");
189+
writer.println("\t/bin/bash -c \"nextclade dataset get --name='sars-cov-2' --output-dir='/work/data/sars-cov-2';nextclade --input-dataset=/work/data/sars-cov-2 --input-fasta '/work/" + consensusFasta.getName() + "' --output-json '/work/" + jsonFile.getName() + "'\" && rm -Rf /work/data");
190190
writer.println("");
191191
writer.println("echo 'Bash script complete'");
192192
writer.println("");
@@ -200,7 +200,7 @@ public static File runNextClade(File consensusFasta, Logger log, PipelineOutputT
200200
rWrapper.setWorkingDir(outputDir);
201201
rWrapper.execute(Arrays.asList("/bin/bash", localBashScript.getName()));
202202

203-
localBashScript.delete();
203+
tracker.addIntermediateFile(localBashScript);
204204

205205
if (!jsonFile.exists())
206206
{
@@ -210,12 +210,18 @@ public static File runNextClade(File consensusFasta, Logger log, PipelineOutputT
210210
return jsonFile;
211211
}
212212

213-
private static JSONObject parseNextClade(File jsonFile) throws PipelineJobException
213+
private static JSONObject parseNextClade(File jsonFile, Logger log) throws PipelineJobException
214214
{
215215
try (InputStream is = IOUtil.openFileForReading(jsonFile))
216216
{
217-
JSONArray samples = new JSONArray(IOUtil.readFully(is));
218-
if (samples.length() != 1)
217+
JSONObject results = new JSONObject(IOUtil.readFully(is));
218+
JSONArray samples = results.getJSONArray("results");
219+
if (samples.length() == 0)
220+
{
221+
log.info("No samples found in NextClade JSON, this probably means no clade was assigned");
222+
return null;
223+
}
224+
else if (samples.length() != 1)
219225
{
220226
throw new PipelineJobException("Expected a single sample, was: " + samples.length());
221227
}
@@ -230,7 +236,11 @@ private static JSONObject parseNextClade(File jsonFile) throws PipelineJobExcept
230236

231237
public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, int analysisId, int libraryId, int alignmentId, int readsetId, File consensusVCF, boolean dbImport) throws PipelineJobException
232238
{
233-
JSONObject sample = parseNextClade(jsonFile);
239+
JSONObject sample = parseNextClade(jsonFile, job.getLogger());
240+
if (sample == null)
241+
{
242+
return;
243+
}
234244

235245
ReferenceGenome genome = SequenceAnalysisService.get().getReferenceGenome(libraryId, job.getUser());
236246
String clade = sample.getString("clade");
@@ -250,7 +260,9 @@ public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, i
250260
return;
251261
}
252262

253-
JSONArray aaSubstitutions = sample.getJSONArray("aaSubstitutions");
263+
List<JSONObject> aaSubstitutions = new ArrayList<>(Arrays.asList(sample.getJSONArray("aaSubstitutions").toJSONObjectArray()));
264+
aaSubstitutions.addAll(Arrays.asList(sample.getJSONArray("aaDeletions").toJSONObjectArray()));
265+
254266
Map<Integer, List<VariantContext>> consensusMap = ViralSnpUtil.readVcfToMap(consensusVCF);
255267

256268
TableInfo aaTable = SequenceAnalysisSchema.getInstance().getSchema().getTable(SequenceAnalysisSchema.TABLE_AA_SNP_BY_CODON);
@@ -264,15 +276,14 @@ public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, i
264276

265277
int refNtId = ts.getObject(Integer.class);
266278

267-
for (int i=0;i<aaSubstitutions.length();i++)
279+
for (JSONObject aa : aaSubstitutions)
268280
{
269-
JSONObject aa = aaSubstitutions.getJSONObject(i);
270281
int pos = aa.getInt("codon");
271282
pos = pos + 1; //make 1-based
272283

273284
String aaName = aa.getString("gene");
274285

275-
JSONObject range = aa.getJSONObject("nucRange");
286+
JSONObject range = aa.getJSONObject("codonNucRange");
276287
List<Integer> positions = new ArrayList<>();
277288
//Range is 0-based
278289
for (int p = range.getInt("begin") + 1;p <= range.getInt("end"); p++)
@@ -342,6 +353,7 @@ public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, i
342353
Double af;
343354
Double dp;
344355

356+
List<String> ntPositions = new ArrayList<>();
345357
if (vcList.size() == 1)
346358
{
347359
depth = (double)vcList.get(0).getAttributeAsInt("GATK_DP", 0);
@@ -350,6 +362,8 @@ public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, i
350362
alleleDepth = (double)depths.get(2) + depths.get(3);
351363
dp = (double)vcList.get(0).getAttributeAsInt("DP", 0);
352364
af = vcList.get(0).getAttributeAsDouble("AF", 0.0);
365+
366+
ntPositions.add(String.valueOf(vcList.get(0).getStart()));
353367
}
354368
else
355369
{
@@ -363,6 +377,8 @@ public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, i
363377

364378
af = vcList.stream().mapToDouble(x -> x.getAttributeAsDouble("AF", 0)).summaryStatistics().getAverage();
365379
dp = vcList.stream().mapToDouble(x -> x.getAttributeAsDouble("DP", 0)).summaryStatistics().getAverage();
380+
381+
vcList.forEach(vc -> ntPositions.add(String.valueOf(vc.getStart())));
366382
}
367383

368384
int refAaId = ViralSnpUtil.resolveGene(refNtId, aaName);
@@ -376,7 +392,7 @@ public static void processAndImportNextCladeAa(PipelineJob job, File jsonFile, i
376392
aaRow.put("ref_aa", aa.getString("refAA"));
377393
aaRow.put("q_aa", aa.getString("queryAA"));
378394
aaRow.put("codon", aa.getString("queryCodon"));
379-
aaRow.put("ref_nt_positions", StringUtils.join(positions, ","));
395+
aaRow.put("ref_nt_positions", StringUtils.join(ntPositions, ","));
380396

381397
aaRow.put("readcount", alleleDepth);
382398
aaRow.put("depth", depth);

jbrowse/src/client/JBrowse/Browser/plugins/ExtendedVariantPlugin/ExtendedVariantWidget/ExtendedVariantWidget.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,18 @@ export default jbrowse => {
7474
if (value){
7575
if (Array.isArray(value)){
7676
const children = []
77+
78+
let idx = 0
7779
for (let val in value){
80+
idx++;
7881
children.push(
79-
<div className={classes.fieldSubValue}>
82+
<div key={property + "-" + idx} className={classes.fieldSubValue}>
8083
{value[val]}
8184
</div>
8285
)
8386
}
8487
tempProp.push(
85-
<div className={classes.field}>
88+
<div key={property} className={classes.field}>
8689
<div className={classes.fieldName}>
8790
{displays[display].properties[property]}
8891
</div>
@@ -93,11 +96,11 @@ export default jbrowse => {
9396
else {
9497
let tempName = fields[displays[display].properties[property]] ? fields[displays[display].properties[property]].title : displays[display].properties[property]
9598
tempProp.push(
96-
<div className={classes.field}>
97-
<div className={classes.fieldName}>
99+
<div key={property} className={classes.field}>
100+
<div key={property + "-field"} className={classes.fieldName}>
98101
{tempName}
99102
</div>
100-
<div className={classes.fieldValue}>
103+
<div key={property + "-val"} className={classes.fieldValue}>
101104
{value}
102105
</div>
103106
</div>
@@ -113,7 +116,7 @@ export default jbrowse => {
113116
const displayJSX = []
114117
for (let i = 0; i < propertyJSX.length; i++){
115118
displayJSX.push(
116-
<BaseCard title={displays[i].name}>
119+
<BaseCard key={displays[i].name} title={displays[i].name}>
117120
{propertyJSX[i]}
118121
</BaseCard>
119122
)

jbrowse/src/org/labkey/jbrowse/JBrowseServiceImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ public static JBrowseServiceImpl get()
4848
public String prepareOutputFile(User u, Logger log, Integer outputFileId, boolean forceRecreateJson, JSONObject additionalConfig)
4949
{
5050
JsonFile ret = JsonFile.prepareJsonFileRecordForOutputFile(u, outputFileId, additionalConfig, log);
51+
if (ret != null && ret.needsProcessing())
52+
{
53+
try
54+
{
55+
ret.prepareResource(log, false, true);
56+
}
57+
catch (PipelineJobException e)
58+
{
59+
log.error("Unable to prepare JBrowse resource: " + outputFileId, e);
60+
}
61+
}
5162

5263
return ret == null ? null : ret.getObjectId();
5364
}

jbrowse/test/src/org/labkey/test/tests/external/labModules/JBrowseTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ private By getVariantWithinTrack(String trackId, String variantText, boolean wai
134134

135135
if (waitFor)
136136
{
137-
waitForElement(l);
137+
waitForElement(l, WAIT_FOR_JAVASCRIPT * 2);
138138
}
139139

140140
// Not ideal, but this might fix intermittent failures due to loading

0 commit comments

Comments
 (0)