Skip to content

Commit

Permalink
adding computeDigestFragments and getDigestFragsForSeqAndEnzymes func…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
tnrich committed Sep 7, 2022
1 parent 6445f75 commit 7c15d45
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 11,454 deletions.
151 changes: 151 additions & 0 deletions src/computeDigestFragments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
const { flatMap, cloneDeep } = require("lodash");
const bsonObjectId = require("bson-objectid");

const {
normalizePositionByRangeLength,
getRangeLength
} = require("ve-range-utils");
const getCutsitesFromSequence = require("./getCutsitesFromSequence");

function computeDigestFragments({
cutsites,
sequenceLength,
circular,
//optional:
computePartialDigest,
computeDigestDisabled,
computePartialDigestDisabled,
selectionLayerUpdate,
updateSelectedFragment
}) {
const fragments = [];
const overlappingEnzymes = [];
const pairs = [];

const sortedCutsites = cutsites.sort((a, b) => {
return a.topSnipPosition - b.topSnipPosition;
});
if (!circular) {
sortedCutsites.push({
id: "seqTerm_" + bsonObjectId().str,
start: 0,
end: 0,
overhangBps: "",
topSnipPosition: 0,
bottomSnipPosition: 0,
upstreamTopSnip: 0,
upstreamBottomSnip: 0,
upstreamTopBeforeBottom: false,
topSnipBeforeBottom: false,
recognitionSiteRange: {
start: 0,
end: 0
},
forward: true,
name: "Sequence_Terminus",
restrictionEnzyme: {
name: "Sequence_Terminus"
}
});
}

sortedCutsites.forEach((cutsite1, index) => {
if (computePartialDigest && !computePartialDigestDisabled) {
sortedCutsites.forEach((cs, index2) => {
if (index2 === index + 1 || index2 === 0) {
return;
}
pairs.push([cutsite1, sortedCutsites[index2]]);
});
}
if (!computeDigestDisabled) {
pairs.push([
cutsite1,
sortedCutsites[index + 1]
? sortedCutsites[index + 1]
: sortedCutsites[0]
]);
}
});

pairs.forEach(r => {
let [cut1, cut2] = r;

const start = normalizePositionByRangeLength(
cut1.topSnipPosition,
sequenceLength
);
const end = normalizePositionByRangeLength(
cut2.topSnipPosition - 1,
sequenceLength
);
const size = getRangeLength({ start, end }, sequenceLength);

// const id = uniqid()
let isFormedFromLinearEnd;
if (cut1.name === "Sequence_Terminus") {
cut1 = cloneDeep(cut1);
isFormedFromLinearEnd = true;
cut1.name = "Linear_Sequence_Start";
cut1.restrictionEnzyme.name = "Linear_Sequence_Start";
} else if (cut2.name === "Sequence_Terminus") {
cut2 = cloneDeep(cut2);
isFormedFromLinearEnd = true;
cut2.name = "Linear_Sequence_End";
cut2.restrictionEnzyme.name = "Linear_Sequence_End";
}

const id = start + "-" + end + "-" + size + "-";
const name = `${cut1.restrictionEnzyme.name} -- ${cut2.restrictionEnzyme.name} ${size} bps`;
getRangeLength({ start, end }, sequenceLength);

fragments.push({
isFormedFromLinearEnd,
madeFromOneCutsite: cut1 === cut2,
start,
end,
size,
id,
name,
cut1,
cut2,
onFragmentSelect:
selectionLayerUpdate && updateSelectedFragment
? () => {
selectionLayerUpdate({
start,
end,
name
});

updateSelectedFragment(id);
}
: undefined
});
});
fragments.filter(fragment => {
if (!fragment.size) {
overlappingEnzymes.push(fragment);
return false;
}
return true;
});
return {
computePartialDigestDisabled,
computeDigestDisabled,
fragments,
overlappingEnzymes
};
}

function getDigestFragsForSeqAndEnzymes({ sequence, circular, enzymes }) {
const cutsitesByName = getCutsitesFromSequence(sequence, circular, enzymes);
return computeDigestFragments({
cutsites: flatMap(cutsitesByName),
sequenceLength: sequence.length,
circular
});
}

module.exports.computeDigestFragments = computeDigestFragments;
module.exports.getDigestFragsForSeqAndEnzymes = getDigestFragsForSeqAndEnzymes;
44 changes: 44 additions & 0 deletions src/computeDigestFragments.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const {
getDigestFragsForSeqAndEnzymes
} = require("./computeDigestFragments.js");
const aliasedEnzymesByName = require("./aliasedEnzymesByName");

describe("computeDigestFragments", function() {
it.only("it should correctly generate fragments for bamhi cutting once in a circular sequence", function() {
const result = getDigestFragsForSeqAndEnzymes({
sequence: "ggggatccggggggggggggggggggggggggggggggggggggggggg",
circular: true,
enzymes: [aliasedEnzymesByName.bamhi]
});
expect(result.fragments).toHaveLength(1);
expect(result.fragments[0].start).toEqual(3);
expect(result.fragments[0].end).toEqual(2);
expect(result.fragments[0].size).toEqual(49);
expect(result.fragments[0].madeFromOneCutsite).toEqual(true);
});
it("it should correctly generate fragments for bamhi cutting once in a linear sequence", function() {
const result = getDigestFragsForSeqAndEnzymes({
sequence: "ggggatccggggggggggggggggggggggggggggggggggggggggg",
circular: false,
enzymes: [aliasedEnzymesByName.bamhi]
});
expect(result.fragments).toHaveLength(2);
expect(result.fragments[0].isFormedFromLinearEnd).toEqual(true);
expect(result.fragments[0].name).toEqual(
"BamHI -- Linear_Sequence_End 46 bps"
);
expect(result.fragments[0].start).toEqual(3);
expect(result.fragments[0].end).toEqual(48);
expect(result.fragments[0].size).toEqual(46);
expect(result.fragments[0].madeFromOneCutsite).toEqual(false);

expect(result.fragments[1].isFormedFromLinearEnd).toEqual(true);
expect(result.fragments[1].name).toEqual(
"Linear_Sequence_Start -- BamHI 3 bps"
);
expect(result.fragments[1].start).toEqual(0);
expect(result.fragments[1].end).toEqual(2);
expect(result.fragments[1].size).toEqual(3);
expect(result.fragments[1].madeFromOneCutsite).toEqual(false);
});
});
16 changes: 3 additions & 13 deletions src/cutSequenceByRestrictionEnzyme.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { assign } = require("lodash");
const bsonObjectId = require("bson-objectid");

const getReverseComplementSequenceString = require("./getReverseComplementSequenceString");

const {
Expand All @@ -12,19 +14,6 @@ module.exports = function cutSequenceByRestrictionEnzyme(
circular,
restrictionEnzyme
) {
// ac.throw([
// ac.string,
// ac.bool,
// ac.shape({
// "name": ac.string,
// "site": ac.string,
// "forwardRegex": ac.string,
// "reverseRegex": ac.string,
// "cutsTwice": ac.number,
// "topSnipOffset": ac.number,
// "bottomSnipOffset": ac.number
// })
// ], arguments);
if (
restrictionEnzyme.forwardRegex.length === 0 ||
restrictionEnzyme.reverseRegex.length === 0
Expand Down Expand Up @@ -280,6 +269,7 @@ function cutSequence(
let overhangBps = getSequenceWithinRange(cutRange, originalSequence);

restrictionCutSite = {
id: bsonObjectId().str,
start,
end,
topSnipPosition,
Expand Down
4 changes: 2 additions & 2 deletions src/generateSequenceData.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// var ac = require('ve-api-check');
const { generateRandomRange } = require("ve-range-utils");
const objectid = require("bson-objectid");
const bsonObjectId = require("bson-objectid");

module.exports = function generateSequenceData({
isProtein,
Expand Down Expand Up @@ -83,7 +83,7 @@ function generateAnnotation(start, end, maxLength) {
...range,
name: getRandomInt(0, 100000).toString(),
type: "misc_feature",
id: objectid().str,
id: bsonObjectId().str,
forward: Math.random() > 0.5,
notes: {}
};
Expand Down
9 changes: 0 additions & 9 deletions src/getCutsitesFromSequence.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
// const ac = require('ve-api-check');
const cutSequenceByRestrictionEnzyme = require("./cutSequenceByRestrictionEnzyme");

module.exports = function getCutsitesFromSequence(
sequence,
circular,
restrictionEnzymes
) {
//validate args!
// ac.throw([
// ac.string,
// ac.bool,
// ac.array
// ], arguments);

const cutsitesByName = {};
// const allCutsite= [];
for (let i = 0; i < restrictionEnzymes.length; i++) {
const re = restrictionEnzymes[i];
const cutsites = cutSequenceByRestrictionEnzyme(sequence, circular, re);
Expand Down
4 changes: 2 additions & 2 deletions src/getOrfsFromSequence.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const ObjectId = require("bson-objectid");
const bsonObjectId = require("bson-objectid");
const getReverseComplementSequenceString = require("./getReverseComplementSequenceString");
// const ac = require('ve-api-check');
/**
Expand Down Expand Up @@ -73,7 +73,7 @@ module.exports = function getOrfsFromSequence(options) {
forward: forward,
annotationTypePlural: "orfs",
isOrf: true,
id: ObjectId().str
id: bsonObjectId().str
});
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ module.exports.getComplementSequenceAndAnnotations = require("./getComplementSeq
module.exports.getComplementSequenceString = require("./getComplementSequenceString");
module.exports.getCutsitesFromSequence = require("./getCutsitesFromSequence");
module.exports.getCutsiteType = require("./getCutsiteType");
module.exports.computeDigestFragments = require("./computeDigestFragments").computeDigestFragments;
module.exports.getDigestFragsForSeqAndEnzymes = require("./computeDigestFragments").getDigestFragsForSeqAndEnzymes;
module.exports.getInsertBetweenVals = require("./getInsertBetweenVals");
module.exports.getLeftAndRightOfSequenceInRangeGivenPosition = require("./getLeftAndRightOfSequenceInRangeGivenPosition");
module.exports.getOrfsFromSequence = require("./getOrfsFromSequence");
Expand Down
6 changes: 3 additions & 3 deletions src/tidyUpAnnotation.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { cloneDeep, get } = require("lodash");
const FeatureTypes = require("./FeatureTypes.js");
const featureColors = require("./featureColors");
const bsonObjectid = require("bson-objectid");
const bsonObjectId = require("bson-objectid");

module.exports = function tidyUpAnnotation(
_annotation,
Expand Down Expand Up @@ -34,10 +34,10 @@ module.exports = function tidyUpAnnotation(
annotation.name = "Untitled annotation";
}
if (provideNewIdsForAnnotations) {
annotation.id = bsonObjectid().str;
annotation.id = bsonObjectId().str;
}
if (!annotation.id && annotation.id !== 0 && !doNotProvideIdsForAnnotations) {
annotation.id = bsonObjectid().str;
annotation.id = bsonObjectId().str;
messages.push(
"Unable to detect valid ID for annotation, setting ID to " + annotation.id
);
Expand Down
4 changes: 2 additions & 2 deletions src/tidyUpSequenceData.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// tnrtodo: figure out where to insert this validation exactly..
const bsonObjectid = require("bson-objectid");
const bsonObjectId = require("bson-objectid");
const getAminoAcidDataForEachBaseOfDna = require("./getAminoAcidDataForEachBaseOfDna");
const { cloneDeep, flatMap } = require("lodash");
const annotationTypes = require("./annotationTypes");
Expand Down Expand Up @@ -148,7 +148,7 @@ module.exports = function tidyUpSequenceData(pSeqData, options = {}) {
if (item.id || item.id === 0) {
itemId = item.id;
} else {
itemId = bsonObjectid().str;
itemId = bsonObjectId().str;
if (!doNotProvideIdsForAnnotations) {
item.id = itemId; //assign the newly created id to the item
}
Expand Down
Loading

0 comments on commit 7c15d45

Please sign in to comment.