Skip to content

Commit 5c27488

Browse files
committed
Merge discvr-23.7 to develop
2 parents cbe50ab + d83f6b9 commit 5c27488

File tree

12 files changed

+2142
-1522
lines changed

12 files changed

+2142
-1522
lines changed

jbrowse/package-lock.json

Lines changed: 1705 additions & 1438 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jbrowse/package.json

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
},
1717
"dependencies": {
1818
"@gmod/vcf": "^5.0.10",
19-
"@jbrowse/core": "^2.6.2",
20-
"@jbrowse/plugin-linear-genome-view": "^2.6.2",
21-
"@jbrowse/plugin-svg": "^2.6.2",
22-
"@jbrowse/plugin-variants": "^2.6.2",
23-
"@jbrowse/react-linear-genome-view": "^2.6.2",
19+
"@jbrowse/core": "^2.7.0",
20+
"@jbrowse/plugin-linear-genome-view": "^2.7.0",
21+
"@jbrowse/plugin-svg": "^2.7.0",
22+
"@jbrowse/plugin-variants": "^2.7.0",
23+
"@jbrowse/react-linear-genome-view": "^2.7.0",
2424
"@labkey/api": "^1.25.0",
25-
"@labkey/components": "^2.381.1",
25+
"@labkey/components": "^2.0.0",
2626
"@mui/x-data-grid": "^6.0.1",
2727
"assert": "^2.0.0",
2828
"browserify-zlib": "^0.2.0",
@@ -44,11 +44,10 @@
4444
"typescript": "^5.1.6",
4545
"util": "^0.12.5",
4646
"uuid": "^9.0.0",
47-
"vm-browserify": "^1.1.2",
48-
"xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz"
47+
"vm-browserify": "^1.1.2"
4948
},
5049
"devDependencies": {
51-
"@labkey/build": "6.15.0",
50+
"@labkey/build": "6.16.0",
5251
"@types/jest": "^29.0.0",
5352
"@types/jexl": "^2.3.1",
5453
"@types/jquery": "^3.0.0",

jbrowse/src/client/JBrowse/Browser/Browser.spec.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ jest.mock('@labkey/api', () => {
8686
},
8787
ActionURL: {
8888
buildURL: jest.fn()
89-
}
89+
},
90+
getServerContext: jest.fn(() => {
91+
return {devMode: true}
92+
})
9093
}
9194
})
9295
const mockedRequest = mocked(Ajax)
@@ -110,7 +113,7 @@ describe('JBrowse 2 Browser', () => {
110113
return {} as XMLHttpRequest;
111114
});
112115
const wrapper = mount(<View />);
113-
expect(wrapper.find('.MuiPaper-root')).toHaveLength(2)
116+
expect(wrapper.find('.MuiPaper-root')).toHaveLength(4)
114117
});
115118

116119
});

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export default jbrowse => {
182182
}
183183

184184
const ref = feat["REF"];
185-
const alt = feat["ALT"]
185+
const alt = feat["ALT"] || []
186186

187187
const [state, setState] = useState(null)
188188
useEffect(() => {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React, { useState } from 'react';
2+
import Dialog from '@mui/material/Dialog';
3+
import Button from '@mui/material/Button';
4+
import Tooltip from '@mui/material/Tooltip';
5+
import HelpIcon from '@mui/icons-material/Help';
6+
import CloseIcon from '@mui/icons-material/Close';
7+
8+
export default function VideoModal({ videoURL, hoverText = '' }) {
9+
const [open, setOpen] = useState(false);
10+
11+
const handleOpen = () => {
12+
setOpen(true);
13+
};
14+
15+
const handleClose = () => {
16+
setOpen(false);
17+
};
18+
19+
const buttonContent = (
20+
<Button
21+
onClick={handleOpen}
22+
disableRipple
23+
style={{
24+
padding: 0,
25+
minWidth: 0,
26+
backgroundColor: 'transparent',
27+
}}
28+
>
29+
<HelpIcon />
30+
</Button>
31+
);
32+
33+
return (
34+
<div>
35+
{hoverText ? (
36+
<Tooltip title={hoverText}>
37+
{buttonContent}
38+
</Tooltip>
39+
) : (
40+
buttonContent
41+
)}
42+
<Dialog
43+
open={open}
44+
onClose={handleClose}
45+
PaperProps={{
46+
style: {
47+
backgroundColor: 'transparent',
48+
boxShadow: 'none',
49+
position: 'relative',
50+
},
51+
}}
52+
>
53+
<CloseIcon
54+
style={{
55+
position: 'absolute',
56+
top: 10,
57+
right: 10,
58+
zIndex: 1,
59+
cursor: 'pointer',
60+
color: 'white',
61+
backgroundColor: 'rgba(0, 0, 0, 0.4)',
62+
borderRadius: '50%'
63+
}}
64+
onClick={handleClose}
65+
/>
66+
<video
67+
width="100%"
68+
controls
69+
>
70+
<source src={videoURL} type="video/mp4" />
71+
Your browser does not support the video tag.
72+
</video>
73+
</Dialog>
74+
</div>
75+
);
76+
}

jbrowse/src/client/JBrowse/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ export async function fetchFieldTypeInfo(sessionId: string, trackId: string, suc
566566
successCallback(fields, groups, promotedFilters)
567567
},
568568
failure: function(res){
569+
console.error(res)
569570
failureCallback("There was an error while fetching field types: " + res.status + "\n Status Body: " + res.statusText + "\n Session ID:" + sessionId)
570571
},
571572
params: {sessionId: sessionId, trackId: trackId},

jbrowse/src/org/labkey/jbrowse/model/JsonFile.java

Lines changed: 57 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.labkey.jbrowse.model;
22

3+
import htsjdk.samtools.util.FileExtensions;
34
import htsjdk.tribble.bed.BEDCodec;
45
import htsjdk.tribble.gff.Gff3Codec;
56
import htsjdk.tribble.index.Index;
@@ -29,6 +30,7 @@
2930
import org.labkey.api.pipeline.PipeRoot;
3031
import org.labkey.api.pipeline.PipelineJobException;
3132
import org.labkey.api.pipeline.PipelineService;
33+
import org.labkey.api.pipeline.PipelineValidationException;
3234
import org.labkey.api.query.FieldKey;
3335
import org.labkey.api.query.QueryService;
3436
import org.labkey.api.query.UserSchema;
@@ -38,17 +40,18 @@
3840
import org.labkey.api.sequenceanalysis.SequenceOutputFile;
3941
import org.labkey.api.sequenceanalysis.pipeline.ReferenceGenome;
4042
import org.labkey.api.sequenceanalysis.pipeline.SequencePipelineService;
41-
import org.labkey.api.sequenceanalysis.run.DISCVRSeqRunner;
4243
import org.labkey.api.sequenceanalysis.run.SimpleScriptWrapper;
4344
import org.labkey.api.settings.AppProps;
4445
import org.labkey.api.util.FileType;
4546
import org.labkey.api.util.FileUtil;
4647
import org.labkey.api.util.GUID;
48+
import org.labkey.api.util.JobRunner;
4749
import org.labkey.api.util.PageFlowUtil;
4850
import org.labkey.api.util.Path;
4951
import org.labkey.api.view.UnauthorizedException;
5052
import org.labkey.jbrowse.JBrowseManager;
5153
import org.labkey.jbrowse.JBrowseSchema;
54+
import org.labkey.jbrowse.pipeline.JBrowseLucenePipelineJob;
5255
import org.labkey.sequenceanalysis.run.util.TabixRunner;
5356

5457
import javax.annotation.Nullable;
@@ -937,25 +940,52 @@ public File prepareResource(Logger log, boolean throwIfNotPrepared, boolean forc
937940
if (shouldHaveFreeTextSearch())
938941
{
939942
File luceneDir = getExpectedLocationOfLuceneIndex(throwIfNotPrepared);
940-
if (forceReprocess && luceneDir.exists())
943+
long sizeInGb = targetFile.length() / (1024 * 1024 * 1024);
944+
log.debug("preparing lucene index, VCF size: " + sizeInGb);
945+
946+
if (!forceReprocess && doesLuceneIndexExist())
941947
{
942-
try
943-
{
944-
FileUtils.deleteDirectory(luceneDir);
945-
}
946-
catch (IOException e)
947-
{
948-
throw new PipelineJobException(e);
949-
}
948+
log.debug("Existing lucene index found, will not re-create: " + luceneDir.getPath());
950949
}
951-
952-
if (forceReprocess || !doesLuceneIndexExist())
950+
else if (sizeInGb > 50)
953951
{
954-
prepareLuceneIndex(log);
952+
log.info("VCF is too large, submitting VcfToLuceneIndexer as a separate pipeline job");
953+
final File vcf = targetFile;
954+
JobRunner.getDefault().execute(() -> {
955+
try
956+
{
957+
PipeRoot root = PipelineService.get().getPipelineRootSetting(getContainerObj());
958+
PipelineService.get().queueJob(new JBrowseLucenePipelineJob(getContainerObj(), null, root, vcf, luceneDir, getInfoFieldsToIndex(), allowLenientLuceneProcessing()));
959+
}
960+
catch (PipelineValidationException e)
961+
{
962+
log.error(e);
963+
}
964+
});
955965
}
956966
else
957967
{
958-
log.debug("Existing lucene index found, will not re-create: " + luceneDir.getPath());
968+
if (forceReprocess && luceneDir.exists())
969+
{
970+
try
971+
{
972+
log.debug("Deleting existing index: " + luceneDir.getPath());
973+
FileUtils.deleteDirectory(luceneDir);
974+
}
975+
catch (IOException e)
976+
{
977+
throw new PipelineJobException(e);
978+
}
979+
}
980+
981+
if (forceReprocess || !doesLuceneIndexExist())
982+
{
983+
JBrowseLucenePipelineJob.prepareLuceneIndex(targetFile, luceneDir, log, getInfoFieldsToIndex(), allowLenientLuceneProcessing());
984+
}
985+
else
986+
{
987+
log.debug("Existing lucene index found, will not re-create: " + luceneDir.getPath());
988+
}
959989
}
960990
}
961991

@@ -987,57 +1017,10 @@ private boolean doesLuceneIndexExist()
9871017
return Arrays.asList(rawFields.split(","));
9881018
}
9891019

990-
private void prepareLuceneIndex(Logger log) throws PipelineJobException
1020+
private boolean allowLenientLuceneProcessing()
9911021
{
992-
log.debug("Generating VCF full text index for file: " + getExpData().getFile().getName());
993-
994-
DISCVRSeqRunner runner = new DISCVRSeqRunner(log);
995-
if (!runner.jarExists())
996-
{
997-
log.error("Unable to find DISCVRSeq.jar, skipping lucene index creation");
998-
return;
999-
}
1000-
1001-
File indexDir = getExpectedLocationOfLuceneIndex(false);
1002-
if (indexDir != null && indexDir.exists())
1003-
{
1004-
try
1005-
{
1006-
FileUtils.deleteDirectory(getExpectedLocationOfLuceneIndex(false));
1007-
}
1008-
catch (IOException e)
1009-
{
1010-
throw new PipelineJobException(e);
1011-
}
1012-
}
1013-
1014-
List<String> args = runner.getBaseArgs("VcfToLuceneIndexer");
1015-
args.add("-V");
1016-
args.add(getExpData().getFile().getPath());
1017-
1018-
args.add("-O");
1019-
args.add(indexDir.getPath());
1020-
1021-
List<String> infoFieldsForFullTextSearch = getInfoFieldsToIndex();
1022-
for (String field : infoFieldsForFullTextSearch)
1023-
{
1024-
args.add("-IF");
1025-
args.add(field);
1026-
}
1027-
1028-
args.add("--allow-missing-fields");
1029-
1030-
args.add("--index-stats");
1031-
args.add(getExpectedLocationOfLuceneIndexStats(false).getPath());
1032-
10331022
JSONObject config = getExtraTrackConfig();
1034-
if (config != null && !config.isNull("lenientLuceneProcessing") && config.getBoolean("lenientLuceneProcessing"))
1035-
{
1036-
args.add("--validation-stringency");
1037-
args.add("LENIENT");
1038-
}
1039-
1040-
runner.execute(args);
1023+
return config != null && !config.isNull("lenientLuceneProcessing") && config.getBoolean("lenientLuceneProcessing");
10411024
}
10421025

10431026
protected void createIndex(File finalLocation, Logger log, File idx, boolean throwIfNotPrepared) throws PipelineJobException
@@ -1095,8 +1078,17 @@ else if (TRACK_TYPES.gff.getFileType().isType(finalLocation) || TRACK_TYPES.gtf.
10951078
SequenceAnalysisService.get().sortGxf(log, finalLocation, null);
10961079
}
10971080

1098-
TabixRunner tabix = new TabixRunner(log);
1099-
tabix.execute(finalLocation);
1081+
// If JBrowse is using an unaltered input file, trust that index:
1082+
File expectedIdx = new File(finalLocation.getPath() + FileExtensions.TABIX_INDEX);
1083+
if (expectedIdx.exists() && getExpData().getFile().equals(finalLocation))
1084+
{
1085+
log.debug("Existing index found, will not re-create: " + expectedIdx.getPath());
1086+
}
1087+
else
1088+
{
1089+
TabixRunner tabix = new TabixRunner(log);
1090+
tabix.execute(finalLocation);
1091+
}
11001092
}
11011093
}
11021094
}
@@ -1372,11 +1364,6 @@ public boolean shouldHaveFreeTextSearch()
13721364
return json != null && json.optBoolean("createFullTextIndex", false);
13731365
}
13741366

1375-
public File getExpectedLocationOfLuceneIndexStats(boolean throwIfNotFound)
1376-
{
1377-
return new File(getExpectedLocationOfLuceneIndex(throwIfNotFound).getPath() + ".stats.txt");
1378-
}
1379-
13801367
public File getExpectedLocationOfLuceneIndex(boolean throwIfNotFound)
13811368
{
13821369
File basedir = getLocationOfProcessedTrack(false);

0 commit comments

Comments
 (0)