jbrowse-plugin-msaview 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LaunchMsaViewExtensionPoint/index.js +5 -2
- package/dist/MsaViewPanel/afterCreateAutoruns.js +21 -1
- package/dist/MsaViewPanel/fetchTabixMsa.d.ts +12 -0
- package/dist/MsaViewPanel/fetchTabixMsa.js +33 -0
- package/dist/MsaViewPanel/types.d.ts +7 -0
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +28 -26
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
- package/src/LaunchMsaViewExtensionPoint/index.ts +10 -1
- package/src/MsaViewPanel/afterCreateAutoruns.ts +30 -1
- package/src/MsaViewPanel/fetchTabixMsa.ts +50 -0
- package/src/MsaViewPanel/types.ts +8 -0
- package/src/version.ts +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export default function LaunchMsaViewExtensionPointF(pluginManager) {
|
|
2
2
|
pluginManager.addToExtensionPoint('LaunchView-MsaView',
|
|
3
3
|
// @ts-expect-error
|
|
4
|
-
({ session, data, msaFileLocation, treeFileLocation, connectedViewId, connectedFeature, displayName, colorSchemeName, colWidth, rowHeight, treeAreaWidth, treeWidth, drawNodeBubbles, labelsAlignRight, showBranchLen, querySeqName, highlightColumns, }) => {
|
|
5
|
-
if (!data && !msaFileLocation) {
|
|
4
|
+
({ session, data, msaFileLocation, msaTabixLocation, msaIndexLocation, msaId, treeFileLocation, connectedViewId, connectedFeature, displayName, colorSchemeName, colWidth, rowHeight, treeAreaWidth, treeWidth, drawNodeBubbles, labelsAlignRight, showBranchLen, querySeqName, highlightColumns, }) => {
|
|
5
|
+
if (!data && !msaFileLocation && !msaTabixLocation) {
|
|
6
6
|
throw new Error('No MSA data or file location provided when launching MSA view');
|
|
7
7
|
}
|
|
8
8
|
session.addView('MsaView', {
|
|
@@ -23,6 +23,9 @@ export default function LaunchMsaViewExtensionPointF(pluginManager) {
|
|
|
23
23
|
msaData: data?.msa,
|
|
24
24
|
treeData: data?.tree,
|
|
25
25
|
msaUrl: msaFileLocation?.uri,
|
|
26
|
+
msaTabixLocation,
|
|
27
|
+
msaIndexLocation,
|
|
28
|
+
msaId,
|
|
26
29
|
treeUrl: treeFileLocation?.uri,
|
|
27
30
|
querySeqName,
|
|
28
31
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSession } from '@jbrowse/core/util';
|
|
2
2
|
import { doLaunchBlast } from './doLaunchBlast';
|
|
3
|
+
import { fetchTabixMsa } from './fetchTabixMsa';
|
|
3
4
|
import { genomeToMSA } from './genomeToMSA';
|
|
4
5
|
import { loadProteinDomains } from './loadProteinDomains';
|
|
5
6
|
import { cleanupOldData, generateDataStoreId, retrieveMsaData, storeMsaData, } from './msaDataStore';
|
|
@@ -121,7 +122,7 @@ export function processInit(self) {
|
|
|
121
122
|
void (async () => {
|
|
122
123
|
try {
|
|
123
124
|
self.setError(undefined);
|
|
124
|
-
const { msaData, msaUrl, treeData, treeUrl, querySeqName } = init;
|
|
125
|
+
const { msaData, msaUrl, msaTabixLocation, msaIndexLocation, msaId, treeData, treeUrl, querySeqName, } = init;
|
|
125
126
|
if (msaUrl) {
|
|
126
127
|
const id = getUniprotIdFromAlphaFoldUrl(msaUrl);
|
|
127
128
|
if (id) {
|
|
@@ -143,6 +144,25 @@ export function processInit(self) {
|
|
|
143
144
|
const data = await response.text();
|
|
144
145
|
self.setMSA(data);
|
|
145
146
|
}
|
|
147
|
+
else if (msaTabixLocation) {
|
|
148
|
+
const feature = self.connectedFeature;
|
|
149
|
+
if (feature) {
|
|
150
|
+
const fasta = await fetchTabixMsa({
|
|
151
|
+
location: msaTabixLocation,
|
|
152
|
+
indexLocation: msaIndexLocation,
|
|
153
|
+
msaId: msaId ?? String(feature.name),
|
|
154
|
+
refName: String(feature.refName),
|
|
155
|
+
start: Number(feature.start),
|
|
156
|
+
end: Number(feature.end),
|
|
157
|
+
});
|
|
158
|
+
if (fasta) {
|
|
159
|
+
self.setMSA(fasta);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
throw new Error(`No alignment for ${msaId ?? String(feature.name)} in ${msaTabixLocation.uri}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
146
166
|
if (treeData) {
|
|
147
167
|
self.setTree(treeData);
|
|
148
168
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function fetchTabixMsa({ location, indexLocation, msaId, refName, start, end, }: {
|
|
2
|
+
location: {
|
|
3
|
+
uri: string;
|
|
4
|
+
};
|
|
5
|
+
indexLocation?: {
|
|
6
|
+
uri: string;
|
|
7
|
+
};
|
|
8
|
+
msaId: string;
|
|
9
|
+
refName: string;
|
|
10
|
+
start: number;
|
|
11
|
+
end: number;
|
|
12
|
+
}): Promise<string | undefined>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { TabixIndexedFile } from '@gmod/tabix';
|
|
2
|
+
import { openLocation } from '@jbrowse/core/util/io';
|
|
3
|
+
// Pull one transcript's whole multiple-alignment out of a locus-keyed tabix
|
|
4
|
+
// file. Each line is `refName<TAB>start<TAB>end<TAB>msaId<TAB>packed`, where
|
|
5
|
+
// `packed` is `name:SEQ;name:SEQ;...` — no newlines, so the alignment survives
|
|
6
|
+
// as a single tabix column. We query the transcript's genomic locus, then pick
|
|
7
|
+
// the line whose msaId matches, and rebuild a FASTA string.
|
|
8
|
+
export async function fetchTabixMsa({ location, indexLocation, msaId, refName, start, end, }) {
|
|
9
|
+
const uri = (loc) => openLocation({ uri: loc.uri, locationType: 'UriLocation' });
|
|
10
|
+
const file = new TabixIndexedFile({
|
|
11
|
+
filehandle: uri(location),
|
|
12
|
+
csiFilehandle: uri(indexLocation ?? { uri: `${location.uri}.csi` }),
|
|
13
|
+
});
|
|
14
|
+
const lines = [];
|
|
15
|
+
await file.getLines(refName, start, end, {
|
|
16
|
+
lineCallback: line => {
|
|
17
|
+
lines.push(line);
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const line = lines.find(l => l.split('\t')[3] === msaId);
|
|
21
|
+
return line ? unpack(line) : undefined;
|
|
22
|
+
}
|
|
23
|
+
function unpack(line) {
|
|
24
|
+
const packed = line.split('\t')[4] ?? '';
|
|
25
|
+
return packed
|
|
26
|
+
.split(';')
|
|
27
|
+
.filter(Boolean)
|
|
28
|
+
.map(pair => {
|
|
29
|
+
const colon = pair.indexOf(':');
|
|
30
|
+
return `>${pair.slice(0, colon)}\n${pair.slice(colon + 1)}`;
|
|
31
|
+
})
|
|
32
|
+
.join('\n');
|
|
33
|
+
}
|