Skip to content

Commit

Permalink
Merge pull request #908 from chgibb/master
Browse files Browse the repository at this point in the history
0.12.0-beta.3
  • Loading branch information
chgibb committed Aug 26, 2019
2 parents 334e3cf + 8524017 commit f94a377
Show file tree
Hide file tree
Showing 24 changed files with 1,879 additions and 391 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -40,7 +40,7 @@ PHAT is under development in the Zehbe Lab ([https://www.zehbelab.com/](https://

Gibb CM, Jackson R, Mohammed S, Fiaidhi J, Zehbe I. Pathogen-Host Analysis Tool (PHAT): an integrative platform to analyze next-generation sequencing data. *Bioinformatics*. 2018. DOI: [10.1093/bioinformatics/bty1003](https://doi.org/10.1093/bioinformatics/bty1003)

### [Latest Beta Release: PHAT@0.12.0-beta.1](https://chgibb.github.io/PHATDocs/releases/0.12.0-beta.1/index)
### [Latest Beta Release: PHAT@0.12.0-beta.2](https://chgibb.github.io/PHATDocs/releases/0.12.0-beta.2/index)

### [Release History](https://chgibb.github.io/PHATDocs/allReleases)

Expand Down
835 changes: 718 additions & 117 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions package.json
Expand Up @@ -45,8 +45,9 @@
"@chgibb/electron-tabs": "^0.8.0",
"@chgibb/ng-node-compile": "^1.0.6",
"@claviska/jquery-minicolors": "^2.2.6",
"@material-ui/core": "^4.0.2",
"@material-ui/core": "^4.3.2",
"@material-ui/icons": "^4.0.1",
"@types/chart.js": "2.7.56",
"@types/fs-extra": "0.0.37",
"@types/jest": "^22.2.2",
"@types/jquery": "^2.0.40",
Expand All @@ -70,6 +71,8 @@
"browserify": "^13.1.0",
"builtin-modules": "^3.1.0",
"bundle-collapser": "^1.2.1",
"chart.js": "2.8.0",
"chartjs-plugin-annotation": "^0.5.7",
"csx": "^9.0.0",
"delete-empty": "^1.0.1",
"dialogs": "^1.1.19",
Expand Down Expand Up @@ -102,6 +105,7 @@
"popper.js": "1.14.4",
"protobufjs": "^6.8.3",
"ps-node": "^0.1.6",
"randomcolor": "^0.5.4",
"react": "^16.7.0",
"react-beautiful-dnd": "^11.0.4",
"react-dom": "^16.7.0",
Expand Down Expand Up @@ -136,4 +140,4 @@
"resources/app"
]
}
}
}
4 changes: 2 additions & 2 deletions scripts/fix.bash
@@ -1,3 +1,3 @@
./node_modules/.bin/eslint "src/**/*.ts" --cache --fix
./node_modules/.bin/eslint "src/**/*.tsx" --fix --cache-location ".eslintcache-tsx"

./node_modules/.bin/eslint "src/**/*.tsx" --cache --fix
./node_modules/.bin/eslint "src/**/*.ts" --fix --cache-location ".eslintcache-ts"
1 change: 1 addition & 0 deletions scripts/rollup.ts
Expand Up @@ -26,6 +26,7 @@
"debounce",
"react-event-listener",
"clsx",
"chart.js",

"@material-ui/core/Button",
"@material-ui/core/Dialog",
Expand Down
8 changes: 8 additions & 0 deletions src/BLASTSegmentProcess.ts
Expand Up @@ -78,12 +78,17 @@ process.on("message",async function(ev : AtomicOperationForkEvent)
{}
);

logger.logObject({message: `Found ${readsWithFragments.length} reads`});

let readsBLASTed = 0;

for(let i = 0; i != readsWithFragments.length; ++i)
{
if(readsWithFragments[i].read.SEQ.length < BLASTLENGTHCUTOFF)
{
logger.logObject({message: `Read ${i} is too small`});
continue;
}

let hasLargeFragment = false;
for(let j = 0; j != readsWithFragments[i].fragments.length; ++ j)
Expand All @@ -95,7 +100,10 @@ process.on("message",async function(ev : AtomicOperationForkEvent)
}
}
if(!hasLargeFragment)
{
logger.logObject({message: `Read ${i} does not have an unmapped fragment of sufficient size`});
continue;
}

//BLAST identified reads
let repeatedSearching = 0;
Expand Down
11 changes: 11 additions & 0 deletions src/outputRenderer.tsx
Expand Up @@ -30,14 +30,24 @@ class OutputApp extends React.Component<{},OutputViewProps>
{
this.setState({fastqs : arg.val});
}

if(arg.key == "fastaInputs" && arg.val !== undefined)
{
this.setState({fastas : arg.val});
}

if(arg.key == "aligns" && arg.val !== undefined)
{
this.setState({aligns : arg.val});
}

if(arg.key == "operations")
{
if(arg.val !== undefined)
{
this.setState({operations : arg.val});
}
}
}
}
);
Expand All @@ -50,6 +60,7 @@ class OutputApp extends React.Component<{},OutputViewProps>
fastqs={this.state.fastqs}
fastas={this.state.fastas}
aligns={this.state.aligns}
operations={this.state.operations}
/>
);
}
Expand Down
14 changes: 13 additions & 1 deletion src/req/fasta.ts
Expand Up @@ -57,4 +57,16 @@ export function getFaiPath(fasta : Fasta) : string
export function get2BitPath(fasta : Fasta) : string
{
return getReadableAndWritable(`rt/indexes/${fasta.uuid}.2bit`);
}
}

export function totalBP(fasta : Fasta) : number
{
let res = 0;

for(let i = 0; i != fasta.contigs.length; ++i)
{
res += fasta.contigs[i].bp;
}

return res;
}
51 changes: 34 additions & 17 deletions src/req/renderer/QCRenderer/QCView.tsx
Expand Up @@ -6,6 +6,9 @@ import {Fastq} from "../../fastq";
import {AtomicOperation} from "../../operations/atomicOperations";
import {QCReportsTable} from "../containers/tables/qCReportsTable";
import {QCReport} from "../containers/qcReport";
import {QCStatusDoughnut} from "../containers/charts/QCStatusDoughnut";
import {GridWrapper} from "../containers/gridWrapper";
import {Grid} from "../components/grid";

import {generateFastQCReport} from "./publish";

Expand Down Expand Up @@ -61,24 +64,38 @@ export class QCView extends React.Component<QCViewProps,QCViewState>

return (
<React.Fragment>
{!this.state.viewingReport ?
<QCReportsTable
data={this.props.fastqs ? this.props.fastqs : []}
shouldAllowTriggeringOps={true}
onGenerateClick={(event, data : Fastq) =>
{!this.state.viewingReport ?
<React.Fragment>
{
event;
generateFastQCReport(data);
}}
onViewReportClick={(event,data : Fastq) =>
{
event;
this.setState({
viewUuid : data.uuid,
viewingReport : true
});
}}
/>
this.props.fastqs !== undefined && this.props.fastqs.length > 0 ?
<GridWrapper>
<Grid container spacing={1} justify="center">
<QCStatusDoughnut
fastqs={this.props.fastqs}
height="50%"
width="50%"
marginBottom="15vh"
/>
</Grid>
</GridWrapper>: ""}
<QCReportsTable
data={this.props.fastqs ? this.props.fastqs : []}
shouldAllowTriggeringOps={this.state.shouldAllowTriggeringOps}
onGenerateClick={(event, data : Fastq) =>
{
event;
generateFastQCReport(data);
}}
onViewReportClick={(event,data : Fastq) =>
{
event;
this.setState({
viewUuid : data.uuid,
viewingReport : true
});
}}
/>
</React.Fragment>
: ""}
{this.state.viewingReport && this.state.viewUuid ?
<QCReport
Expand Down
1 change: 1 addition & 0 deletions src/req/renderer/components/input.ts
@@ -0,0 +1 @@
export const Input : typeof import("@material-ui/core/Input").default = require("@material-ui/core/Input").default;
1 change: 1 addition & 0 deletions src/req/renderer/components/inputLabel.ts
@@ -0,0 +1 @@
export const InputLabel : typeof import("@material-ui/core/InputLabel").default = require("@material-ui/core/InputLabel").default;
42 changes: 42 additions & 0 deletions src/req/renderer/components/outlinedInput.tsx
@@ -0,0 +1,42 @@
import * as React from "react";

import {FormControl} from "./formControl";
import {InputLabel} from "./inputLabel";

const MuiOutlinedInput: typeof import("@material-ui/core/OutlinedInput").default = require("@material-ui/core/OutlinedInput").default;

type MuiOutlinedInputProps = import("@material-ui/core/OutlinedInput/index").OutlinedInputProps;

export interface OutlinedInputProps {
label: string;
inputProps: Omit<MuiOutlinedInputProps, "labelWidth">;
}

export function OutlinedInput(props: OutlinedInputProps): JSX.Element
{
const [labelWidth, setLabelWidth] = React.useState(0);
const labelRef = React.useRef<HTMLLabelElement>(null);

React.useEffect(() =>
{
setLabelWidth(labelRef.current!.offsetWidth);
}, []);

return (
<div style={{
display: "flex",
flexWrap: "wrap"
}}>
<FormControl variant="outlined">
<InputLabel ref={labelRef}>
{props.label}
</InputLabel>
<MuiOutlinedInput
{...props.inputProps}

labelWidth={labelWidth}
/>
</FormControl>
</div>
);
}
133 changes: 133 additions & 0 deletions src/req/renderer/containers/charts/QCStatusDoughnut.tsx
@@ -0,0 +1,133 @@
import * as React from "react";
import {Chart} from "chart.js";

import {Fastq} from "../../../fastq";

export interface QCStatusDoughnutProps {
fastqs: Array<Fastq>;
height: string;
width: string;
marginBottom: string;
}

export class QCStatusDoughnut extends React.Component<QCStatusDoughnutProps, {}>
{
private chartRef = React.createRef<HTMLCanvasElement>();
private chart: Chart | undefined;

public colour1: string;
public colour2: string;
public colour3: string;
public colour4: string;

public constructor(props: QCStatusDoughnutProps)
{
super(props);

const randomColour = require("randomcolor");

this.colour1 = randomColour();
this.colour2 = randomColour();
this.colour3 = randomColour();
this.colour4 = randomColour();
}

public updateChart()
{
let numPass = 0;
let numWarn = 0;
let numFail = 0;
let numNoData = 0;

if (this.props.fastqs)
{
for (let i = 0; i != this.props.fastqs.length; ++i)
{

if (this.props.fastqs[i].QCData.summary && this.props.fastqs[i].QCData.summary.length > 0)
{
for (let j = 0; j != this.props.fastqs[i].QCData.summary.length; ++j)
{
let status = this.props.fastqs[i].QCData.summary[j].status;
console.log(status);
if (status == "pass")
numPass++;
else if (status == "warn")
numWarn++;
else if (status == "fail")
numFail++;
else if (status == "No Data")
numNoData++;
else if (status === undefined)
numNoData++;
}
}
else
numNoData += 5;
}

if (this.chartRef.current)
{
if (!this.chart)
{
this.chart = new Chart(this.chartRef.current.getContext("2d")!, {
type: "doughnut",
options: {
animation: {
animateRotate: true
}
}
});
}

let data = {
datasets: [
{
data: [numPass, numWarn, numFail, numNoData],
backgroundColor: [
this.colour1,
this.colour2,
this.colour3,
this.colour4
]
}
],
labels: [
"Pass",
"Warning",
"Failure",
"No Data"
]
};

console.log(data);
this.chart.data = data;
this.chart.update();
}
}
}

public componentDidUpdate()
{
this.updateChart();
}

public componentDidMount()
{
this.updateChart();
}

public render(): JSX.Element
{
return (
<div style={{
position: "relative",
height: this.props.height,
width: this.props.width,
marginBottom: this.props.marginBottom
}}>
<canvas ref={this.chartRef}></canvas>
</div>
);
}
}

0 comments on commit f94a377

Please sign in to comment.