@opencloning/ui 1.4.3 → 1.4.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @opencloning/ui
2
2
 
3
+ ## 1.4.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#624](https://github.com/manulera/OpenCloning_frontend/pull/624) [`c333aa3`](https://github.com/manulera/OpenCloning_frontend/commit/c333aa3f5eda8ab7a65799d589ba6e9b376e2d24) Thanks [@manulera](https://github.com/manulera)! - Assigning plasmids to categories handles palindromic parts
8
+
9
+ - Updated dependencies []:
10
+ - @opencloning/store@1.4.4
11
+ - @opencloning/utils@1.4.4
12
+
3
13
  ## 1.4.3
4
14
 
5
15
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencloning/ui",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -25,8 +25,8 @@
25
25
  "@emotion/styled": "^11.14.0",
26
26
  "@mui/icons-material": "^5.15.17",
27
27
  "@mui/material": "^5.15.17",
28
- "@opencloning/store": "1.4.3",
29
- "@opencloning/utils": "1.4.3",
28
+ "@opencloning/store": "1.4.4",
29
+ "@opencloning/utils": "1.4.4",
30
30
  "@teselagen/bio-parsers": "^0.4.34",
31
31
  "@teselagen/ove": "^0.8.34",
32
32
  "@teselagen/range-utils": "^0.3.20",
@@ -1,6 +1,7 @@
1
1
  import { isRangeWithinRange } from '@teselagen/range-utils';
2
2
  import { getComplementSequenceString, getAminoAcidFromSequenceTriplet, getDigestFragmentsForRestrictionEnzymes, getReverseComplementSequenceString } from '@teselagen/sequence-utils';
3
3
  import { allSimplePaths } from 'graphology-simple-path';
4
+ import { openCycleAtNode } from './graph_utils';
4
5
 
5
6
  export function tripletsToTranslation(triplets) {
6
7
  if (!triplets) return ''
@@ -100,6 +101,13 @@ export function getSimplifiedDigestFragments(sequenceData, enzymes) {
100
101
  return simplifiedDigestFragments.concat(simplifiedDigestFragmentsRc);
101
102
  }
102
103
 
104
+ export function isFragmentPalindromic(fragment) {
105
+ return (
106
+ (fragment.left.ovhg === getReverseComplementSequenceString(fragment.left.ovhg)) &&
107
+ (fragment.right.ovhg === getReverseComplementSequenceString(fragment.right.ovhg))
108
+ )
109
+ }
110
+
103
111
  export function assignSequenceToSyntaxPart(sequenceData, enzymes, graph) {
104
112
  // Something that is important to understand here is the meaning of forward and reverse.
105
113
  // It does not mean whether the overhang is 5' or 3', the value on the top strand is always
@@ -111,7 +119,8 @@ export function assignSequenceToSyntaxPart(sequenceData, enzymes, graph) {
111
119
  simplifiedDigestFragments
112
120
  .filter(f => f.left.forward && !f.right.forward && graph.hasNode(f.left.ovhg) && graph.hasNode(f.right.ovhg))
113
121
  .forEach(fragment => {
114
- const paths = allSimplePaths(graph, fragment.left.ovhg, fragment.right.ovhg);
122
+ const graphForPaths = isFragmentPalindromic(fragment) ? openCycleAtNode(graph, graph.nodes()[0]) : graph;
123
+ const paths = allSimplePaths(graphForPaths, fragment.left.ovhg, fragment.right.ovhg);
115
124
  if (paths.length > 0) {
116
125
  foundParts.push({left_overhang: fragment.left.ovhg, right_overhang: fragment.right.ovhg, longestFeature: fragment.longestFeature});
117
126
  }
@@ -1,6 +1,8 @@
1
- import { aliasedEnzymesByName, getDigestFragmentsForRestrictionEnzymes, getReverseComplementSequenceString, getComplementSequenceString } from "@teselagen/sequence-utils";
2
- import { assignSequenceToSyntaxPart, simplifyDigestFragment, reverseComplementSimplifiedDigestFragment, tripletsToTranslation, partDataToDisplayData, arrayCombinations } from "./assembler_utils";
1
+ import { aliasedEnzymesByName, getDigestFragmentsForRestrictionEnzymes, getReverseComplementSequenceString, getComplementSequenceString, getReverseComplementSequenceAndAnnotations } from "@teselagen/sequence-utils";
2
+ import fs from 'fs';
3
+ import { assignSequenceToSyntaxPart, simplifyDigestFragment, reverseComplementSimplifiedDigestFragment, tripletsToTranslation, partDataToDisplayData, arrayCombinations, getSimplifiedDigestFragments } from "./assembler_utils";
3
4
  import { partsToEdgesGraph } from "./graph_utils";
5
+ import { genbankToJson } from '@teselagen/bio-parsers';
4
6
 
5
7
  const sequenceBsaI = 'tgggtctcaTACTagagtcacacaggactactaAATGagagacctac';
6
8
  const sequenceBsaI2 = 'tgggtctcaAATGagagtcacacaggactactaAGGTagagacctac'
@@ -28,6 +30,30 @@ describe('reverseComplementSimplifiedDigestFragment', () => {
28
30
  });
29
31
  });
30
32
 
33
+
34
+
35
+ it('handles palindromic fragments', () => {
36
+
37
+ const parts = [
38
+ {left_overhang: 'AATT', right_overhang: 'AGCT'}, // This part is palindromic, should only be picked up in AATT-AGCT, not AGCT-AATT
39
+ {left_overhang: 'AGCT', right_overhang: 'GGAG'},
40
+ {left_overhang: 'GGAG', right_overhang: 'AATT'},
41
+ ]
42
+ // Read file
43
+ const sequence = 'tgggtctcaAATTagagtcacacaggactactaAGCTagagacctac'
44
+ const seqData = { sequence, circular: true };
45
+ const result = assignSequenceToSyntaxPart(seqData, [aliasedEnzymesByName["bsai"]], partsToEdgesGraph(parts));
46
+
47
+ expect(result).toEqual([{left_overhang: 'AATT', right_overhang: 'AGCT', longestFeature: null}]);
48
+
49
+ const seqDataRc = getReverseComplementSequenceAndAnnotations(seqData);
50
+ const resultRc = assignSequenceToSyntaxPart(seqDataRc, [aliasedEnzymesByName["bsai"]], partsToEdgesGraph(parts));
51
+
52
+ expect(resultRc).toEqual([{left_overhang: 'AATT', right_overhang: 'AGCT', longestFeature: null}]);
53
+
54
+ });
55
+
56
+
31
57
  it('shows the meaning of forward and reverse', () => {
32
58
  const sequence = 'aaGGTCTCaTACTaaa'
33
59
  const digestFragments = getDigestFragmentsForRestrictionEnzymes(
@@ -40,9 +40,11 @@ export function partsToEdgesGraph(parts) {
40
40
 
41
41
  // Break cycles by removing incoming edges to a node
42
42
  export function openCycleAtNode(graph, cutNode) {
43
- for (const edge of graph.inEdges(cutNode)) {
44
- graph.dropEdge(edge);
43
+ const newGraph = graph.copy();
44
+ for (const edge of newGraph.inEdges(cutNode)) {
45
+ newGraph.dropEdge(edge);
45
46
  }
47
+ return newGraph;
46
48
  }
47
49
 
48
50
  // Convert DAG to MSA-like matrix (rows = paths, columns = topological generations)
@@ -142,8 +144,7 @@ function minimumCoveringRows(msa) {
142
144
 
143
145
  export function graphToMSA(graph) {
144
146
  if (graph.nodes().length === 0) return [];
145
- const newGraph = graph.copy();
146
- openCycleAtNode(newGraph, newGraph.nodes()[0]);
147
+ const newGraph = openCycleAtNode(graph, graph.nodes()[0]);
147
148
  return minimumCoveringRows(dagToMSA(newGraph));
148
149
  }
149
150
 
@@ -114,9 +114,9 @@ describe('openCycleAtNode', () => {
114
114
  graph.addEdge('C', 'B'); // Creates cycle
115
115
 
116
116
  expect(graph.inDegree('B')).toBe(2);
117
- openCycleAtNode(graph, 'B');
118
- expect(graph.inDegree('B')).toBe(0);
119
- expect(graph.outDegree('B')).toBe(1);
117
+ const newGraph = openCycleAtNode(graph, 'B');
118
+ expect(newGraph.inDegree('B')).toBe(0);
119
+ expect(newGraph.outDegree('B')).toBe(1);
120
120
 
121
121
  });
122
122
 
@@ -127,9 +127,9 @@ describe('openCycleAtNode', () => {
127
127
  graph.addEdge('A', 'B');
128
128
  graph.addEdge('B', 'A'); // Cycle
129
129
 
130
- openCycleAtNode(graph, 'A');
131
- expect(graph.outDegree('A')).toBe(1);
132
- expect(graph.hasEdge('A', 'B')).toBe(true);
130
+ const newGraph = openCycleAtNode(graph, 'A');
131
+ expect(newGraph.outDegree('A')).toBe(1);
132
+ expect(newGraph.hasEdge('A', 'B')).toBe(true);
133
133
  });
134
134
 
135
135
  it('handles node with no incoming edges', () => {
@@ -138,9 +138,9 @@ describe('openCycleAtNode', () => {
138
138
  graph.addNode('B');
139
139
  graph.addEdge('A', 'B');
140
140
 
141
- openCycleAtNode(graph, 'A');
142
- expect(graph.inDegree('A')).toBe(0);
143
- expect(graph.hasEdge('A', 'B')).toBe(true);
141
+ const newGraph = openCycleAtNode(graph, 'A');
142
+ expect(newGraph.inDegree('A')).toBe(0);
143
+ expect(newGraph.hasEdge('A', 'B')).toBe(true);
144
144
  });
145
145
  });
146
146
 
@@ -6,7 +6,7 @@ import { updateEditor } from '@teselagen/ove';
6
6
  import EnzymeMultiSelect from '../../../form/EnzymeMultiSelect';
7
7
  import { stringIsNotDNA } from '@opencloning/store/cloning_utils';
8
8
  import { usePrimerDesign } from './PrimerDesignContext';
9
- import { isEnzymePalyndromic } from '@opencloning/utils/enzyme_utils';
9
+ import { isEnzymePalindromic } from '@opencloning/utils/enzyme_utils';
10
10
 
11
11
  function RestrictionSpacerForm() {
12
12
  const { primerDesignSettings } = usePrimerDesign();
@@ -39,7 +39,7 @@ function RestrictionSpacerForm() {
39
39
  <FormControl sx={{ width: '10em', mt: 1.5, mr: 2 }}>
40
40
  <EnzymeMultiSelect value={leftEnzyme} setEnzymes={(v) => updateEnzymeSettings({ left_enzyme: v })} label="Left enzyme" multiple={false} />
41
41
  </FormControl>
42
- {leftEnzyme && !isEnzymePalyndromic(leftEnzyme) && (
42
+ {leftEnzyme && !isEnzymePalindromic(leftEnzyme) && (
43
43
  <FormControlLabel
44
44
  control={<Checkbox checked={leftEnzymeInverted} onChange={(e) => updateEnzymeSettings({ left_enzyme_inverted: e.target.checked })} />}
45
45
  label="Invert site"
@@ -50,7 +50,7 @@ function RestrictionSpacerForm() {
50
50
  <FormControl sx={{ width: '10em', mt: 1.5, mr: 2 }}>
51
51
  <EnzymeMultiSelect value={rightEnzyme} setEnzymes={(v) => updateEnzymeSettings({ right_enzyme: v })} label="Right enzyme" multiple={false} />
52
52
  </FormControl>
53
- {rightEnzyme && !isEnzymePalyndromic(rightEnzyme) && (
53
+ {rightEnzyme && !isEnzymePalindromic(rightEnzyme) && (
54
54
  <FormControlLabel
55
55
  control={<Checkbox checked={rightEnzymeInverted} onChange={(e) => updateEnzymeSettings({ right_enzyme_inverted: e.target.checked })} />}
56
56
  label="Invert site"
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Version placeholder - replaced at publish time via prepack script
2
- export const version = "1.4.3";
2
+ export const version = "1.4.4";