优化点总结
1.使用 Plotly.react() 代替 Plotly.newPlot(),加快绘图速度。
2.去除 @linked_gene_ids,防止 <a> 标签导致 JavaScript 解析问题。
✅ 确保 data 里的值是数值,避免 null 或字符串影响 Plotly 解析。
✅ 改用 document.addEventListener("DOMContentLoaded", function() {...}) 确保 DOM 先加载。
✅ 提前渲染 div,避免 JavaScript 过早执行而找不到 div。
这样应该可以提高速度和稳定性,你可以试试看! 🚀
#经过严格测试,发现1.不使用json速度会很快; 2.把js文件放到本地/var/www/html/Artocarpus/javascript/文件夹下速度很快.以下为修改后的代码:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use CGI;
use List::Util qw(max min);
# 创建 CGI 对象并设置缓冲
$CGI::DISABLE_UPLOADS = 1; # 禁用文件上传以提高性能
my $cgi = CGI->new;
# 设置数据库配置
my %db_config = (
host => "localhost",
name => "IlexGD",
user => "IGD",
pass => "IGDsecret",
table => "heatmapTest"
);
# 优化基因ID处理并添加错误检查
my $gene_ids_input = $cgi->param('GeneID') || ''; # 添加默认值防止未初始化警告
if (!$gene_ids_input) {
print $cgi->header(-type => 'text/html', -charset => 'UTF-8');
print "Error: No gene IDs provided.";
exit;
}
my @gene_ids = do {
local $/ = "\n";
grep { /\S/ }
map { s/^\s+|\s+$//g; $_ }
split(/\n/, $gene_ids_input);
};
# 检查是否有有效的基因ID
if (!@gene_ids) {
print $cgi->header(-type => 'text/html', -charset => 'UTF-8');
print "Error: No valid gene IDs found.";
exit;
}
# 优化的数据库连接
my $dbh = DBI->connect(
"DBI:mysql:database=$db_config{name};host=$db_config{host}",
$db_config{user},
$db_config{pass},
{
RaiseError => 1,
AutoCommit => 1,
mysql_enable_utf8mb4 => 1,
mysql_auto_reconnect => 1,
mysql_read_default_group => 'client',
mysql_compression => 1,
mysql_connect_timeout => 5,
PrintError => 0,
}
) or die "数据库连接失败: $DBI::errstr";
# 移除查询缓存相关设置,因为在新版MySQL中已不支持
# 仅保留必要的性能优化设置
$dbh->do("SET SESSION sort_buffer_size = 4194304");
# 使用预处理语句查询数据
my $placeholders = join(',', ('?') x @gene_ids);
my $sql = "SELECT * FROM $db_config{table} WHERE geneId IN ($placeholders)";
# 添加错误处理
my $sth;
eval {
$sth = $dbh->prepare($sql);
$sth->execute(@gene_ids);
};
if ($@) {
print $cgi->header(-type => 'text/html', -charset => 'UTF-8');
print "Database error: " . $DBI::errstr;
$dbh->disconnect if $dbh;
exit;
}
# 获取列名和数据
my $columns = $sth->{NAME};
shift @$columns; # 移除 gene_id 列
# 处理数据
my @processed_data;
my ($min_val, $max_val) = (9999, -9999);
while (my $row = $sth->fetchrow_arrayref) {
my @values = map {
my $val = sprintf("%.2f", $_);
$min_val = $val if $val < $min_val;
$max_val = $val if $val > $max_val;
$val;
} @$row[1..$#$row];
push @processed_data, \@values;
}
# 检查是否有数据返回
if (!@processed_data) {
$sth->finish;
$dbh->disconnect;
print $cgi->header(-type => 'text/html', -charset => 'UTF-8');
print "Error: No data found for the provided gene IDs.";
exit;
}
$sth->finish;
$dbh->disconnect;
# 生成JS数组字符串
my $data_str = "[\n";
foreach my $row (@processed_data) {
$data_str .= "[" . join(",", @$row) . "],\n";
}
$data_str =~ s/,\n$/\n/; # 移除最后一个逗号
$data_str .= "]";
my $columns_str = "[" . join(",", map {"'$_'"} @$columns) . "]";
my $gene_ids_str = "[" . join(",", map {
my $escaped = CGI::escapeHTML($_);
"'<a href=\"searchGene.cgi?$escaped\">$escaped</a>'"
} @gene_ids) . "]";
# 确保在输出任何内容之前设置header
print $cgi->header(
-type => 'text/html',
-charset => 'UTF-8',
-expires => '+1h',
-cache_control => 'public, max-age=3600'
);
print <<HTML;
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Keywords" content="shrimp">
<meta name="Description" content="genomic database">
<link href="../../Artocarpus/css/dropdown.css" rel="stylesheet" type="text/css">
<link href="../../Artocarpus/css/buttonstyle.css" rel="stylesheet" type="text/css">
<link href="../../Artocarpus/css/style.css" rel="stylesheet" type="text/css">
<title>IlexPortal - a portal of shrimp multi-omics data</title>
<script src="../../Artocarpus/javascript/plotly-2.14.0.min.js"></script>
<script language="JavaScript">
function displaySubMenu(li) {
var subMenu = li.getElementsByTagName("ul")[0];
subMenu.style.display = "block";
}
function hideSubMenu(li) {
var subMenu = li.getElementsByTagName("ul")[0];
subMenu.style.display = "none";
}
</script>
</head>
<body>
<table width="100%" cellspacing="0" cellpadding="0" bgcolor="#fff">
<tr bgcolor="#B3C2C7">
<td align="center" height="60">
<map name="FPMap0">
<area href="../../Arctocarpus/index.html" shape="rect" coords="22, 2, 261, 59">
</map>
<img usemap="#FPMap0" runat="server" src="../../Artocarpus/images/logo.gif" hspace="0" vspace="0" border="0" width="1200" height="60">
</td>
</tr>
<tr><td><hr></td></tr>
<tr>
<td class="menu" align="center" height="30">
<table width="1200px">
<tr><td>
<div class="nav">
<ul>
<!-- Your menu structure here -->
</ul>
</div>
</td></tr>
</table>
</td>
</tr>
<tr><td align="center">
<table cellpadding="0" bordercolorlight="#C0C0C0" cellspacing="15px" bgcolor="#EEEEEE" border="0" width="1200px">
<tr><td>
<table class="tableborder" width="100%" cellpadding="0" cellspacing="15px" bgcolor="#F5F5F5">
<tr><td align="center"><h2>shrimp Expression Atlas</h2></td></tr>
<tr><td><p> </p></td></tr>
<tr><td>
<table class="tableborder" width="100%" cellpadding="0" cellspacing="15px" bgcolor="#ffffff">
<tr><td width=10%><b>Species</b>:</td><td><a href="genome.cgi?ID=Pcl"><i>Procambarus clarkii</i></a></td></tr>
<tr><td><b>Description</b>:</td><td>Transcriptomic analysis of the epidermis in Procambarus clarkii under different temperature stresses</td></tr>
<tr><td valign=top><b>Experiment</b>:</td><td>T25 (epidermis under 25^C), T35 (epidermis under 35^C), T room (epidermis under room temperature), control (epid>
</table>
</td></tr>
<tr><td> </td></tr>
<tr><td><b>Available analyses for Selected Genes:</b></td></tr>
<tr><td align="center">
<div id="heatmap" style="width: 100%; height: 600px;"></div>
<script>
// 直接使用JavaScript数组,避免JSON解析
const data = $data_str;
const columns = $columns_str;
const geneIds = $gene_ids_str;
// 使用 requestIdleCallback 在浏览器空闲时初始化图表
(window.requestIdleCallback || window.setTimeout)(() => {
const heatmapTrace = [{
z: data,
x: columns,
y: geneIds,
type: 'heatmap',
colorscale: 'Viridis',
zmin: $min_val,
zmax: $max_val,
hoverongaps: false,
showscale: true,
colorbar: {
thickness: 20,
len: 0.5
}
}];
const layout = {
width: 1130,
height: 500,
margin: {
l: 150,
t: 50,
r: 50,
b: 50
},
xaxis: {
side: 'top',
title: 'Samples',
automargin: true,
tickangle: -45
},
yaxis: {
title: 'Expression of Genes(Log2FPKM)',
automargin: true
},
font: {
size: 10
}
};
const config = {
responsive: true,
displayModeBar: true,
displaylogo: false,
scrollZoom: true,
toImageButtonOptions: {
format: 'svg',
filename: 'heatmap',
height: 500,
width: 1130,
scale: 1
}
};
Plotly.react('heatmap', heatmapTrace, layout, config);
});
</script>
</td></tr>
</table>
</td></tr>
</table>
</td></tr>
<tr><td>
<table cellpadding="0" cellspacing="0" bgcolor="#B3C2C7" width="100%" height="120px">
<tr><td class="menu" style="padding-left:20px; padding-top:20px; padding-right:20px; padding-bottom:20px;" align="center">
<table cellpadding="0" cellspacing="15px" align="center" border="0" width="1200px" height="100%">
<tr><td align="left"><font color="#333333"><b>shrimpPortal</b> is developed by <a href="mailto:huxiaoao.com">Yuning Hu</a> in Freshwater Fisheries Research Institute >
This website is compatible with <a target="_blank" href="https://www.google.com/chrome/">Chrome</a> and <a target="_blank" href="https://www.mozilla.org/en-US/firefox>
<td align="right"><img alt="logo" src="../../shrimpPortal/images/logo.jpg" width="80" border="0"></td></tr>
</table>
</td></tr>
</table>
</td></tr>
</table>
</body>
</html>