模块设计&编写
工作总结
编写完成DNA/RNA/Protein使用模型进行预测的表单部分模块编写
组件
DNA/RNA/Protein序列分析预测
代码结构(以DNA为例)
本模块的目的在于用户输入已知DNA序列,通过选择平台上现存的DNA模型(可以是用户自己使用上文中序列模型训练模块训练出来的模型,也可以是使用其他人或本平台提供的模型),让平台使用此模型对输入序列进行分析、预测其特性。
<Box>
<Paper elevation={3}>
<StyledHeader icon={<Input />}>Model selection</StyledHeader>
<Box padding={2}>
<RadioGroup
value={Number(useCustomModel)}
onChange={e => setUseCustomModel(Boolean(parseInt(e.target.value)))}
row
>
<FormControlLabel
value={1}
control={<Radio />}
label="Use my trained model"
/>
<FormControlLabel
value={0}
control={<Radio />}
label="Run the default annotation task"
/>
</RadioGroup>
<Divider/>
<Collapse in={useCustomModel}>
<Box display="flex" alignItems="flex-start" mt={1}>
<TextField
label="Job ID"
value={jobID}
onChange={e => setJobID(e.target.value)}
size="small"
error={Boolean(jobIDHelper)}
helperText={jobIDHelper}
disabled={jobIDConfirmed}
/>
<Box display="flex" alignItems="center" mt="2px">
<LoadingButton
onClick={search}
loading={searching}
loadingPosition="start"
startIcon={<Search />}
variant="contained"
sx={{ ml: 1, mr: 1 }}
>
Search
</LoadingButton>
{jobIDConfirmed ? (
<Button
onClick={() => setJobIDConfirmed(false)}
variant="contained"
color="gray"
sx={{ width: 125 }}
>
<Close />
cancel
</Button>
) : (
<Button
onClick={() => setJobIDConfirmed(true)}
variant="contained"
color="lightSuccess"
disabled={!showJobDetail}
sx={{ width: 125 }}
>
<CheckRounded />
confirm
</Button>
)}
<Grow in={jobIDConfirmed} orientation="horizontal">
<Typography
variant="body2"
>
<CheckCircleOutlineRounded />
Confirmed Job ID: {jobID}
</Typography>
</Grow>
</Box>
</Box>
<Collapse in={showJobDetail}>
<TableContainer component={Paper} sx={{ mt: 2 }}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Job Type</TableCell>
<TableCell>Training Mode</TableCell>
<TableCell>Model Used</TableCell>
<TableCell>Param Compare</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>{jobSearchResult.type}</TableCell>
<TableCell>{jobSearchResult.mode}</TableCell>
<TableCell>
{jobSearchResult.modelCompare
.split(" ")
.map((code, index) => (
<Chip
label={codeMap[code]}
key={index}
/>
))}
</TableCell>
<TableCell>{jobSearchResult.paramCompare}</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Collapse>
</Collapse>
<Collapse in={!useCustomModel}>
<FormControl>
<FormLabel>Select one parameter</FormLabel>
<RadioGroup
value={defaultTask}
onChange={e => setDefaultTask(e.target.value)}
row
>
<FormControlLabel value="4" control={<Radio />} label="4mc" />
<FormControlLabel value="5" control={<Radio />} label="5mc" />
<FormControlLabel value="6" control={<Radio />} label="6mc" />
</RadioGroup>
<FormHelperText></FormHelperText>
</FormControl>
</Collapse>
</Box>
</Paper>
<Paper elevation={3} sx={{ overflow: "hidden", marginTop: 2 }}>
<StyledHeader icon={<ArticleOutlined />}>
Input target sequences
</StyledHeader>
<Box padding={2}>
<RadioGroup
value={Number(useCustomData)}
onChange={e => setUseCustomData(Boolean(parseInt(e.target.value)))}
row
>
<FormControlLabel
value="1"
control={<Radio />}
label="Use custom sequences"
/>
<FormControlLabel
value="0"
control={<Radio />}
label="Use preset sequences"
/>
</RadioGroup>
<Divider sx={{ marginBottom: 2 }} />
<Collapse in={useCustomData}>
<FastaForm fasta={fasta} setFasta={setFasta} type="DNA"/>
</Collapse>
<Collapse in={!useCustomData}>
<Box>
<TextField
value={species}
onChange={e => {
setSpecies(e.target.value);
setChromosome("");
}}
label="Select one species"
size="small"
select
sx={{ minWidth: 300 }}
>
{speciesData.map(s => (
<MenuItem key={s.value} value={s.value}>
{s.label}
</MenuItem>
))}
</TextField>
<TextField
value={chromosome}
onChange={e => setChromosome(e.target.value)}
label="Select one chromosome"
size="small"
select
disabled={!species}
sx={{ marginLeft: 1, minWidth: 300 }}
>
{!species
? []
: speciesData
.find(s => s.value === species)
.chromosomes.map(c => (
<MenuItem key={c.value} value={c.value}>
{c.label}
</MenuItem>
))}
</TextField>
<Box sx={{ width: 300, marginTop: 2 }}>
<Typography gutterBottom>Gene Range</Typography>
<Box sx={{ paddingLeft: 2, paddingRight: 2 }}>
<Slider
value={geneRange}
onChange={(e, v) => setGeneRange(v)}
valueLabelDisplay="auto"
aria-labelledby="range-slider"
marks={[
{ value: 0, label: "0" },
{ value: 100, label: "100" },
]}
/>
</Box>
</Box>
</Box>
</Collapse>
</Box>
</Paper>
<Paper elevation={3} sx={{ marginTop: 2, overflow: "hidden" }}>
<StyledHeader icon={<CloudUploadOutlined />}>Submission</StyledHeader>
<Box margin={2}>
<TextField
value={email}
onChange={({ target: { value } }) => {
setEmail(value);
}}
label="E-mail address"
fullWidth
sx={{ mb: 2 }}
/>
<Typography variant="body2" component="div" marginBottom={2}>
Model training usually takes a long time, depending on the size of
the data. Hence, we strongly recommend you to leave your e-mail
address below so that you will be notified by email when the job is
done.
</Typography>
<Box marginTop={2}>
<LoadingButton
onClick={submit}
loading={uploading}
variant="contained"
loadingPosition="start"
startIcon={<Upload />}
>
submit
</LoadingButton>
<Button
onClick={resetData}
color="error"
variant="outlined"
sx={{ marginLeft: 1 }}
>
reset
</Button>
<Button
onClick={gotoExample}
variant="outlined"
sx={{ marginLeft: 1 }}
>
result example
</Button>
</Box>
</Box>
</Paper>
</Box>
本模块的表单数据也很复杂,包括了序列输入、模型选择这两个重要的功能点;为了实现较好的可视化效果,我还采用了较多的修饰,使用css/sx(MUI API)对组件的样式进行较多调整。
总结
完成这个组件后,我的工作就基本上完成了。此组件的表单虽较模型训练时更简单,但是由于需要实现较好的可视化效果还是存在大量不可复用的代码。但是仍然可以借鉴训练模型时的组件,将重复代码整理,复制到此模块中,降低一部分代码量编写工作。此表单包含模型选择、序列上传两个重要功能,是生物工作者使用本平台的最重要模块(生物工作者不需要AI模型,只需要此模型对未知序列的分析结果)