RNA-seq全流程

第一部分:脚本的初始设置与参数解析

#!/bin/bash

# 检查输入参数
if [ "$#" -lt 1 ]; then
    echo "Usage: $0 -f <sample_file> -d <data_directory> -s <script_directory> -g <group_file>"
    exit 1
fi

# 使用 R 语言的 argparser 包解析命令行参数
Rscript parse_args.R "$@" > args.sh

# 加载解析出的参数
if [ ! -f args.sh ]; then
    echo "Error: args.sh not found, something went wrong in the argument parsing."
    exit 1
fi

# 加载解析出的参数
source ~/yiyaoran/rna-seq/my_rna_seq/1516-ran/args.sh

# 打印所有变量以进行调试
echo "SAMPLE_FILE: $SAMPLE_FILE"
echo "DATADIR: $DATADIR"
echo "SCRIPTDIR: $SCRIPTDIR"
echo "GROUP_FILE: $GROUP_FILE"

# 设置脚本在出现错误时停止
set -e
讲解:
  1. 参数检查:脚本首先检查是否传递了足够的参数,至少需要1个参数。如果不满足条件,则打印使用方法并退出。
  2. 参数解析:使用Rscript调用R脚本parse_args.R来解析命令行参数,并将结果保存为args.sh文件。
  3. 加载参数:如果解析成功,脚本会加载args.sh中的变量,这些变量将用于后续分析(如SAMPLE_FILE, DATADIR等)。
  4. 调试输出:脚本通过echo打印加载的参数值,便于调试和确认输入是否正确。
  5. 设置错误中断set -e命令确保在出现任何错误时,脚本立即停止执行。

第二部分:FastQC 质量控制

# 确保 FastQC 输出目录存在
#OUTPUT_DIR="./1.fastqc_results"
#mkdir -p $OUTPUT_DIR

# 读取样本文件并对每个样本进行 FastQC 分析
#while IFS= read -r sample; do
#    if [[ -f "$sample" ]]; then
#        echo "Processing $sample with FastQC..."
#        fastqc "$sample" -o "$OUTPUT_DIR"
#    else
#        echo "File not found: $sample"
#    fi
#done < "$SAMPLE_FILE"

#echo "FastQC analysis complete. Results are stored in $OUTPUT_DIR."

第三部分:数据质控处理(fastp)

# 设置工作目录和相关路径
workdir=$(pwd)
mkdir -p "$workdir/2.data_qc"
cd "$workdir/2.data_qc"

# 提取样本名称列表
declare -a samples=()

while IFS= read -r sample; do
    # 从路径中提取样本名,假设样本名格式为 {sample}_R1.fq.gz 或 {sample}_R2.fq.gz
    basename=$(basename "$sample")
    sample_name="${basename%_*}"
    if [[ ! " ${samples[*]} " =~ " ${sample_name} " ]]; then
        samples+=("$sample_name")
    fi
done < "$SAMPLE_FILE"

# 运行 fastp 进行质控处理
for i in "${samples[@]}"; do 
    echo "RUN CMD: fastp --thread 4 --qualified_quality_phred 10 \
    --unqualified_percent_limit 50 \
    --n_base_limit 10 \
    -i $DATADIR/${i}_R1.fq.gz \
    -I $DATADIR/${i}_R2.fq.gz \
    -o ${i}_1.clean.fq.gz \
    -O ${i}_2.clean.fq.gz \
    --adapter_fasta $DATADIR/illumina_multiplex.fa \
    -h ${i}.html -j ${i}.json"

    fastp --thread 4 \                            # 使用4个线程并行处理
    --qualified_quality_phred 10 \            # 设置合格碱基的质量值阈值为10,低于该值的碱基视为不合格
    --unqualified_percent_limit 50 \          # 如果一条read中超过50%的碱基不合格,则该read会被过滤掉
    --n_base_limit 10 \                       # 如果一条read中N碱基的数量超过10个,则该read会被过滤掉
    -i $DATADIR/${i}_R1.fq.gz \               # 输入文件1(R1方向的测序数据,gzip压缩格式)
    -I $DATADIR/${i}_R2.fq.gz \               # 输入文件2(R2方向的测序数据,gzip压缩格式)
    -o ${i}_1.clean.fq.gz \                   # 输出清理后的文件1(R1方向)
    -O ${i}_2.clean.fq.gz \                   # 输出清理后的文件2(R2方向)
    --detect_adapter_for_pe \                 # 自动检测并去除双端测序中的接头序列
    -h ${i}.html \                            # 生成HTML格式的质控报告
    -j ${i}.json                              # 生成JSON格式的质控报告

done

# 质控数据统计汇总:
python $SCRIPTDIR/qc_stat.py -d "$workdir/2.data_qc/" -o "$workdir/2.data_qc/" -p all_sample_qc
#csvlook all_sample_qc.tsv 
| SampleID    | rawDataReads | cleanDataReads |   rawDataBase | cleanDataBase |   Q20 |   Q30 |    GC |
| ----------- | ------------ | -------------- | ------------- | ------------- | ----- | ----- | ----- |
| 1516-714T-2 |   46,811,722 |     46,810,452 | 7,021,758,300 | 6,948,101,453 | 98.55 | 95.95 | 55.32 |
| 1516-714W-1 |   46,263,762 |     46,262,678 | 6,939,564,300 | 6,875,725,469 | 98.36 | 95.39 | 55.27 |
| 1516-715T-4 |   41,997,012 |     41,995,142 | 6,299,551,800 | 6,235,252,339 | 98.58 | 96.02 | 55.21 |
| 1516-715W-3 |   41,437,680 |     41,436,064 | 6,215,652,000 | 6,149,566,109 | 98.33 | 95.37 | 56.29 |

echo "Data QC with fastp complete. Results are stored in $workdir/2.data_qc."
  1. 提取样本名称
    • 使用while循环读取样本文件($SAMPLE_FILE),通过提取文件名的前缀部分(假设格式为{sample}_R1.fq.gz)来生成样本名称列表。

第四部分:Reads 与基因组进行比对(HISAT2 和 Samtools 处理)

# 定义参考基因组索引和基因组 BED 文件路径
REF_INDEX="/public/home/2022099/yiyaoran/rna-seq/my_rna_seq/ref/maize/Zea_mays.Zm-B73-REFERENCE-NAM-5.0.dna.toplevel"
GENE_BED="/public/home/2022099/yiyaoran/rna-seq/my_rna_seq/ref/maize/gene.bed"

cd $workdir  # 回到工作目录
mkdir -p $workdir/3.map/hisat2  # 创建比对结果目录
cd $workdir/3.map/hisat2

# 运行 HISAT2 进行比对
for i in "${samples[@]}"; do
    echo "RUN CMD: hisat2 -p 4 --rg-id=${i} --rg SM:${i} --rg LB:${i} --rg PL:ILLUMINA \
    -x $REF_INDEX --dta  \
    -1 $workdir/2.data_qc/${i}_1.clean.fq.gz \
    -2 $workdir/2.data_qc/${i}_2.clean.fq.gz \
    -S ${i}.sam 2>${i}.summary"
  
 	##hisat2软件,链特异性文库设置
	#--rna-strandness RF or FR(RF: read 1是反向链,read 2是正向链)
	#非链特异性文库,不设置此参数
  
   hisat2 -p 4 \                                    # 使用4个线程进行比对
    --rg-id=${i} \                               # 添加read组ID(read group ID),设置为当前样本ID
    --rg SM:${i} \                               # 添加样本名称(sample),设置为当前样本ID
    --rg LB:${i} \                               # 添加文库ID(library),设置为当前样本ID
    --rg PL:ILLUMINA \                           # 指定测序平台为Illumina
    -x $REF_INDEX \                              # 指定参考基因组的索引文件
    --dta \                                      # 为转录组分析(downstream transcriptome analysis)优化比对
    -1 $workdir/2.data_qc/${i}_1.clean.fq.gz \   # 输入清理后的R1方向的reads
    -2 $workdir/2.data_qc/${i}_2.clean.fq.gz \   # 输入清理后的R2方向的reads
    -S ${i}.sam \                                # 输出SAM格式的比对结果文件
    2>${i}.summary                               # 将比对的日志信息输出到summary文件中

done
#cat 1516-714T-2.summary
#23405226 reads; of these:
#  23405226 (100.00%) were paired; of these:
#    1221258 (5.22%) aligned concordantly 0 times
#    20874507 (89.19%) aligned concordantly exactly 1 time
#    1309461 (5.59%) aligned concordantly >1 times
#    ----
#    1221258 pairs aligned concordantly 0 times; of these:
#      84254 (6.90%) aligned discordantly 1 time
#    ----
#    1137004 pairs aligned 0 times concordantly or discordantly; of these:
#      2274008 mates make up the pairs; of these:
#        1292738 (56.85%) aligned 0 times
#       895745 (39.39%) aligned exactly 1 time
#        85525 (3.76%) aligned >1 times
#97.24% overall alignment rate
#- **总共有 23405226 条 reads**:
#  - 其中,**100.00%**(即 23405226 条 reads)都是成对的 paired-end reads;
  
#- 在这些成对的 reads 中:
#  - **5.22%**(1221258 对)完全没有比对上;
#  - **89.19%**(20874507 对)正好比对上1次;
 # - **5.59%**(1309461 对)比对上多于1次;
  
#- **1221258 对 reads** 没有成对的比对上(即 concordantly 0 次),其中:
#  - **6.90%**(84254 对)在不一致的情况下比对上了1次(即 discordantly 1 次);
  
#- **1137004 对 reads** 没有成对地比对上,也没有在不一致的情况下比对上,其中:
#  - 这些未比对上的 reads 共有 **2274008 个单端 mates**(构成这些配对),其中:
#    - **56.85%**(1292738 条 reads)没有比对上;
#    - **39.39%**(895745 条 reads)比对上了1次;
#    - **3.76%**(85525 条 reads)比对上了多于1次。

#- **总体比对率为 97.24%**:这是指所有 reads 中成功比对上的比例,说明数据的比对质量较高。


# sam 转换为 bam 并排序
for i in "${samples[@]}"; do
    echo "RUN CMD: samtools sort --threads 4 -m 3G -o ${i}.bam ${i}.sam"
    samtools sort --threads 4 -m 3G -o ${i}.bam ${i}.sam
done

# bam index 建立索引
for i in "${samples[@]}"; do
    echo "RUN CMD: samtools index ${i}.bam"
    samtools index ${i}.bam
done

第五部分:对 Map 结果进行 QC 分析

主要使用RSeQC的·geneBody_coverage.py工具进行
geneBody_coverage.py 是 RSeQC 工具包中的一个脚本,主要用于评估 RNA-seq 数据中基因覆盖的均匀性。它帮助研究者检测 RNA 样本是否在转录本的 5’ 端到 3’ 端具有均匀的覆盖,从而评估样本 RNA 是否发生了降解。这种分析非常重要,因为 RNA 降解会导致数据偏差,影响下游基因表达分析的准确性。

主要功能:

geneBody_coverage.py 通过对参考基因组的注释文件(通常是 GTF 格式)和 RNA-seq 比对结果(如 BAM 文件)的分析,生成一个覆盖曲线图,显示基因从 5’ 端到 3’ 端的覆盖情况。

常见参数:

  • -r:输入基因组注释文件(GTF 或 BED 格式),指定基因的区域。
  • -i:输入 RNA-seq 的比对文件(BAM 格式),其中包含了比对到基因组上的 reads。
  • -o:指定输出文件的前缀,脚本会生成相应的输出文件,包括覆盖情况的图表和数据。

输出结果:

  1. 覆盖曲线图(gene body coverage plot):该图展示了基因组从 5’ 端到 3’ 端的覆盖分布。如果 RNA 没有显著降解,覆盖应该在基因全长上比较均匀。
  2. 数值文件:包含覆盖数据,方便进一步分析。

工作流程:

  1. 脚本首先将基因的转录本分成 100 个等长区间,从 5’ 端到 3’ 端计算每个区间的覆盖率。
  2. 然后,它汇总所有基因的覆盖情况,绘制覆盖曲线图。
  3. 如果 RNA 样本在处理过程中发生了降解,通常会看到覆盖从 5’ 端到 3’ 端逐渐下降的趋势。

使用示例:

geneBody_coverage.py -r Homo_sapiens.GRCh38.104.gtf -i sample1.bam -o sample1.genebody
cd $workdir  # 回到工作目录
mkdir -p $workdir/3.map/map_QC  # 创建QC结果目录
cd $workdir/3.map/map_QC

# 片段 inner size 分析,检测片段选择是否异常
for i in "${samples[@]}"; do
    echo "RUN CMD: inner_distance.py -i $workdir/3.map/hisat2/${i}.bam  -r $GENE_BED  -o ${i}_inner_size"
    inner_distance.py -i $workdir/3.map/hisat2/${i}.bam  -r $GENE_BED  -o ${i}_inner_size
done

# 基因覆盖度分析,检测RNA是否降解
for i in "${samples[@]}"; do
    echo "RUN CMD: geneBody_coverage.py -r $GENE_BED -i $workdir/3.map/hisat2/${i}.bam  -o ${i}.genebody"
    geneBody_coverage.py -r $GENE_BED -i $workdir/3.map/hisat2/${i}.bam  -o ${i}.genebody
done

echo "Read mapping and QC complete. Results are stored in $workdir/3.map."

在这里插入图片描述
基因覆盖情况图(Gene Body Coverage Plot)
解释:这张图显示了基因从5’端到3’端的覆盖率(Coverage)。图中横轴代表基因的百分比位置(从5’端到3’端),纵轴是覆盖率。
含义:这张图用来评估RNA样本是否发生了降解。理想情况下,基因的覆盖应该是均匀的,呈现出像钟形的分布。图中显示的覆盖从5’端到3’端逐渐升高,随后平稳,然后再到3’端逐渐下降。这种形状表明RNA样本的质量较好,没有显著降解。
在这里插入图片描述
mRNA片段插入大小分布图(mRNA Insert Size Distribution)
解释:这张图展示了插入片段大小(即文库中测序到的片段长度)的分布情况,横轴是插入大小(bp),纵轴是密度。
含义:片段大小分布用来评估文库构建的质量。正常的插入片段大小分布应符合预期,通常在一个范围内具有峰值。在这张图中,片段大小的均值为负值(-40.65 bp),这可能表明数据中有不对称的片段分布,可能是由于实验过程中某些步骤出错了,比如片段过短或异常的反转录反应。

第六部分:基因表达定量及结果展示

cd $workdir/  # 回到工作目录
mkdir -p 4.expression  # 创建基因表达定量结果目录
cd 4.expression

# GTF 文件路径
GTF_FILE="/public/home/2022099/yiyaoran/rna-seq/my_rna_seq/ref/maize/Zea_mays.Zm-B73-REFERENCE-NAM-5.0.59.gtf"
GENE_LENGTH="/public/home/2022099/yiyaoran/rna-seq/my_rna_seq/ref/maize/gene_length.txt"

# 使用 htseq-count 进行基因表达定量
for i in "${samples[@]}"; do
    echo "RUN CMD: htseq-count --format bam --order pos --mode union \
    --stranded no --minaqual 10 --type exon \
    --idattr gene_id $workdir/3.map/hisat2/${i}.bam $GTF_FILE > ${i}_gene.tsv"
    
    htseq-count \
    --format bam \                     # 输入文件格式为 BAM
    --order pos \                      # 按照比对结果中的位置顺序进行计数
    --mode union \                     # 使用 "union" 模式进行计数,表示一个 read 覆盖多个 exon 时,按最大重叠区域进行计数
    --stranded no \                    # 指定为非链特异性测序数据
    --minaqual 10 \                    # 只计入测序质量分值大于或等于10的 reads
    --type exon \                      # 只对注释文件中的 exon 类型进行计数
    --idattr gene_id \                 # 使用基因ID(gene_id)作为基因的唯一标识
    $workdir/3.map/hisat2/${i}.bam \   # 输入 BAM 文件(比对结果文件)
    $GTF_FILE > ${i}_gene.tsv          # GTF 文件作为注释,并将结果输出到对应的 gene TSV 文件中
    
    #cat 1516-714T-2_gene.tsv |head -n 3
    #Zm00001eb000010	149
	#Zm00001eb000020	1729
	#Zm00001eb000030	0

done

# 合并不同样品的基因表达定量结果
MERGE_CMD="python $SCRIPTDIR/merge_gene_count.py -p all_gene_count"  # 初始化命令,指定合并的基因计数脚本和输出文件名

for i in "${samples[@]}"; do                                          # 遍历样本数组中的每个样本
    MERGE_CMD+=" -f ${i}_gene.tsv -l ${i}"                            # 为每个样本添加基因计数文件及对应标签参数
done

echo "RUN CMD: $MERGE_CMD"                                           
eval $MERGE_CMD                                                     


# 基因表达定量结果展示
Rscript $SCRIPTDIR/fpkm_and_plot.R -i all_gene_count.tsv -l $GENE_LENGTH -o ./

echo "Gene expression quantification complete. Results are stored in $workdir/4.expression."

第七部分:基因差异表达分析(DESeq2)及可视化

cd $workdir/  # 回到工作目录
mkdir -p 5.deg  # 创建差异表达基因(DEG)分析结果目录
cd 5.deg

# 使用 DESeq2 进行差异表达分析
Rscript ~/yiyaoran/rna-seq/my_rna_seq/scripts/deseq_analysis.r \
-i $workdir/4.expression/all_gene_count.tsv \
-g $GROUP_FILE \
-k $workdir/4.expression/all_gene_fpkm.tsv \
-r W --fdr 0.01 --fc 2 -p $(basename $GROUP_FILE .compare.txt)

# 绘制差异表达基因热图
Rscript ~/yiyaoran/rna-seq/my_rna_seq/scripts/heatmap.r \
-i $workdir/4.expression/all_gene_fpkm.tsv \
-l $(basename $GROUP_FILE .compare.txt).DEG.final.tsv \
-p $(basename $GROUP_FILE .compare.txt).deg_gene_heatmap \
-o ./

echo "Differential expression analysis complete. Results are stored in $workdir/5.deg."

使用R包DEseq2进行进行差异表达分析

library("DESeq2")
#==============================================
#            读取readcount矩阵文件              #
#==============================================
countdata <- read.csv("CountMatrix.csv",header = T,row.names = 1)
head(countdata, 10)

#生成分组信息
coldata <- read.csv("sample.csv",header = T)
#ID	group
#1516-714W-1	W
#1516-715W-3	W
#1516-714T-2	T
#1516-715T-4	T

#关键步骤,生成Deseq对象
dds <- DESeqDataSetFromMatrix(countData = countdata,colData = coldata,design = ~ group)


#==============================================
#              查看DESeqDataSet对象           #
#==============================================
dim(dds)
assay(dds)
assayNames(dds)
colSums(assay(dds))
rowRanges(dds)
colData(dds)


#过滤没有reads比对上的基因,所有reads数为零
nrow(dds)
dds <- dds[rowSums(counts(dds)) > 1 , ]
nrow(dds)
colSums(assay(dds))
barplot(colSums(assay(dds)),las=3,col=rep(rainbow(4),each=2))
#==============================================
#                 差异表达计算                 #
#==============================================

dep <- DESeq(dds)
res <- results(dep)
res
write.csv(x = res,file = "des.csv")


#筛选出差异表达基因,log2foldchange >=1或者<=-1,并且q值小于0.05的基因
res <- na.omit(res)
res0.05 <- res[(abs(res$log2FoldChange)>=1 & res$padj <=0.05), ]
nrow(res0.05)

#筛选出差异表达基因,log2foldchange >=2,并且q值小于0.01的基因
res0.01 <- res[(abs(res$log2FoldChange)>=1 & res$padj <=0.01), ]
nrow(res0.01)

write.csv(res0.05,file = "res0.05.csv")
#找出差异表达最显著的基因,按log2差异倍数排序
head(res0.05[order(res0.05$log2FoldChange,decreasing = TRUE), ])
head(res0.05[order(res0.05$log2FoldChange,decreasing = FALSE), ])
#==============================================
#                  结果可视化                 #
#==============================================
#MA图
plotMA(res, ylim = c(-10,10))

#火山图
m <- res
head(m)
m <- na.omit(m)
plot(m$log2FoldChange,m$padj)
plot(m$log2FoldChange,-1*log10(m$padj))
plot(m$log2FoldChange,-1*log10(m$padj),xlim = c(-10,10),ylim=c(0,100))
m <- transform(m,padj=-1*log10(m$padj))
down <- m[m$log2FoldChange<=-1,] 
up <- m[m$log2FoldChange>=1,]
no <- m[m$log2FoldChange>-1 & m$log2FoldChange <1,] 

plot(no$log2FoldChange,no$padj,xlim = c(-10,10),ylim=c(0,100),col="blue",pch=16,
     cex=0.8,main = "Gene Expression",
     xlab = "log2FoldChange",ylab="-log10(Qvalue)")

points(up$log2FoldChange,up$padj,col="red",pch=16,cex=0.8)
points(down$log2FoldChange,down$padj,col="green",pch=16,cex=0.8)
abline(v = c(-1,1),h = 2)

脚本讲解(未完待续)

deseq_analysis.r 
# 加载 getopt 包,用于解析命令行参数
library(getopt)

第二部分:抽象样本分组信息
# 抽象样本分组矩阵函数
abstract_factors <- function(file) {
  # 读取分组信息文件
  f_mat <- read.table(file, header = TRUE, check.names = FALSE)
  
  # 返回分组矩阵
  return(f_mat)
}


第三部分:双条件差异表达分析函数
# 定义双条件差异表达分析函数
std_two_condition_comp_deseq2 <- function(f_mat, args, data) {
  
  # 加载DESeq2库
  library("DESeq2")
  
  # 提取分组信息
  condition <- f_mat[, 2]
  print(condition)
  
  # 确认分组是否为两个水平
  level <- length(levels(as.factor(condition)))
  if (level != 2) {
    stop("分组的水平数量必须等于2")
  }
  
  # 创建差异表达分析对象
  con <- as.factor(condition)
  print(con)
  
  # 创建DESeq2的数据集对象
  colData <- data.frame(condition = f_mat[, 2])
  rownames(colData) <- f_mat[, 1]
  dds <- DESeqDataSetFromMatrix(countData = data,
                                colData = colData,
                                design = ~ condition)
  
  # 重新设定参考组
  dds$condition <- relevel(dds$condition, ref = opt$ref)
  
  # 运行差异表达分析
  dds <- DESeq(dds)
  res <- results(dds, cooksCutoff = FALSE)
  
  # 输出差异表达分析结果
  print("差异表达分析结果:")
  print(head(res))
  
  # 过滤显著差异表达的基因
# 判断 fold change (FC) 的阈值:
# 如果传入的 opt$fc 参数小于等于 1,则将 fc_cutoff 设为 0;否则,将其设为 log2 转换后的 opt$fc 值
fc_cutoff <- ifelse(as.numeric(opt$fc) <= 1, 0, log2(as.numeric(opt$fc)))

# 判断差异表达基因(DGE)的条件:
# 1. res$padj 小于给定的 FDR 阈值(false discovery rate)
# 2. res$log2FoldChange 的绝对值大于 fc_cutoff(即变化倍数超过设定的阈值)
isDGE <- (res$padj < as.numeric(opt$fdr)) & (abs(res$log2FoldChange) > fc_cutoff)

  
  # 标记显著性
# 将 res$padj 转换为向量,并存储在 significant 变量中
significant <- as.vector(res$padj)

# 将所有 NA 值替换为 "Normal"
significant[is.na(significant)] <- "Normal"

# 将符合显著性阈值(padj < fdr)并且 log2FoldChange 大于 fc_cutoff 的基因标记为 "Up"
significant[(res$padj < as.numeric(opt$fdr)) & (res$log2FoldChange > fc_cutoff)] <- "Up"

# 将符合显著性阈值(padj < fdr)并且 log2FoldChange 小于 -fc_cutoff 的基因标记为 "Down"
significant[(res$padj < as.numeric(opt$fdr)) & (res$log2FoldChange < -fc_cutoff)] <- "Down"

# 对于不显著(padj >= fdr)或 log2FoldChange 在 [-fc_cutoff, fc_cutoff] 之间的基因,标记为 "Normal"
significant[(res$padj >= as.numeric(opt$fdr)) | ((res$log2FoldChange <= fc_cutoff) & (res$log2FoldChange >= -fc_cutoff))] <- "Normal"

# 将 significant 转换为因子类型
significant <- as.factor(significant)

  
  # 输出过滤后的差异表达基因数
  print(paste("显著差异表达基因数量:", sum(isDGE), sep = ""))
  
  # 返回差异表达基因数量
  return(length(isDGE))
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/891370.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2025推荐选题|基于Springboot和vue的智慧阅读管理系统

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

Java - WebSocket

一、WebSocket 1.1、WebSocket概念 WebSocket是一种协议&#xff0c;用于在Web应用程序和服务器之间建立实时、双向的通信连接。它通过一个单一的TCP连接提供了持久化连接&#xff0c;这使得Web应用程序可以更加实时地传递数据。WebSocket协议最初由W3C开发&#xff0c;并于2…

【CSS】houdini自定义CSS属性实现渐变色旋转动画

现有一段代码&#xff0c;在不旋转整个元素的前提下&#xff0c;渐变背景无法应用动画 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initia…

专业模拟训练头显,Varjo XR-4 如何开启虚拟仿真新模拟时代

虚拟仿真模拟训练是提升技能熟练度与工作安全性的有效解决方案&#xff0c;Varjo XR-4作为专业模拟训练头显&#xff0c;凭借其出色的技术特性和性能&#xff0c;正在引领虚拟仿真模拟训练进入一个全新的时代。 一、卓越的视觉体验 高分辨率显示器&#xff1a;Varjo XR-4配备…

计算机毕业设计 基于Python的美术馆预约系统的设计与实现 Python毕业设计 Python毕业设计选题【附源码+安装调试】

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

三子棋(C 语言)

目录 一、游戏设计的整体思路二、各个步骤的代码实现1. 菜单及循环选择的实现2. 棋盘的初始化和显示3. 轮流下棋及结果判断实现4. 结果判断实现 三、所有代码四、总结 一、游戏设计的整体思路 &#xff08;1&#xff09;提供一个菜单让玩家选择人机对战、玩家对战或者退出游戏…

大厂面试真题-组合和聚合的区别是什么

组合和聚合比较类似&#xff0c;二者都表示整体和部分之间的关系。 聚合关系的特点是&#xff1a;整体由部分构成&#xff0c;但是整体和部分之间并不是强依赖的关系&#xff0c;而是弱依 赖的关系&#xff0c;也就是说&#xff0c;即使整体不存在了&#xff0c;部分仍然存在…

Zabbix监控vCenter虚拟机

1. vcenter上配置snmp agent 如果配置 vCenter Server Appliance SNMP 代理以用于轮询,则它可以侦听和响应来自 SNMP 管理客户端系统的请求,如 GET、GETNEXT 和 GETBULK 请求. 使用root身份进入vcenter命令行,开启snmp代理 Command> snmp.enable Command> snmp.set…

正则表达式 | Python、Julia 和 Shell 语法详解

正则表达式在网页爬虫、脚本编写等众多任务中都有重要的应用。为了系统梳理其语法&#xff0c;以及 Python、Julia 和 Shell 中与正则表达式相关的工具&#xff0c;本篇将进行详细介绍。 相关学习资源&#xff1a;编程胶囊。 基础语法 通用语法 在大多数支持正则表达式的语…

24/10/14 视觉笔记 图像拼接融合

图像拼接分为四步 1.特征点提取 2.特征点匹配 3.仿射矩阵计算 4.图像拼接与融合 1.特征提取 找到图像中具有显著性信息点&#xff0c;并计算该点的特征表达 def detectAndDescrible(img):#构建STFT特征检测器sift cv2.SIFT_create()#特征提取kps,features sift.detectA…

3-3 AUTOSAR RTE 对SR Port的实现

返回总目录->返回总目录<- 目录 一、前言 二、显式访问 三、隐式访问 四、队列调用(Queued) 五、无效数据元素 一、前言 RTE作为SWC和BSW之间的通信机构,支持Sender-Receiver方式实现ECU内及ECU间的通信。 对于Sender-Receiver Port支持三种模式: 显式访问:若…

京东零售数据湖应用与实践

作者&#xff1a;陈洪健&#xff1a;京东零售大数据架构师&#xff0c;深耕大数据 10 年&#xff0c;2019 年加入京东&#xff0c;主要负责 OLAP 优化、大数据传输工具生态、流批一体、SRE 建设。 当前企业数据处理广泛采用 Lambda 架构。Lambda 架构的优点是保证了数据的完整性…

LeetCode|70.爬楼梯

这道题很像斐波那契数列&#xff0c;但是初始值不同&#xff0c;也有动态规划的解法&#xff0c;但是一开始我想到的是递归写法。现在我们站在第n阶台阶&#xff0c;那么&#xff0c;我们上一步就有两种可能&#xff1a;1、我们从第n-1阶台阶走一步上来的&#xff1b;2、我们从…

弹出“xinput1_3.dll文件缺失”的错误要怎么处理?一键修复xinput1_3.dll

当你尝试打开游戏或应用时&#xff0c;如果弹出“xinput1_3.dll文件缺失”的错误&#xff0c;请记得及时处理。这个文件是DirectX中用于处理游戏控制器输入的关键组件。这个问题可以通过几个简单的步骤轻松解决。本指南将教你如何快速恢复或替换丢失的xinput1_3.dll文件&#x…

免费Excel工作表同类数据合并工具

下载地址&#xff1a;https://pan.quark.cn/s/81b1aeb45e4c 在 Excel 表格里&#xff0c;当我们试图手动将多行同类数据合并为一行时&#xff0c;会遭遇诸多棘手的困难以及繁杂的操作流程。在确定哪些数据属于可合并的同类数据时&#xff0c;单纯依靠人工进行对比&#xff0c;极…

SQL数据库刷题sql_day33(连续3次为球队得分的球员名单)

描述 两支篮球队进行了激烈的比赛&#xff0c;比分交替上升。比赛结束后&#xff0c;你有一个两队分数的明细表&#xff08;名称为“分数表”&#xff09;。 表中记录了球队、球员号码、球员姓名、得分分数及得分时间。现在球队要对比赛中表现突出的球员进行奖励。 问题&#x…

用最短长度的绳子把整个花园围起来

给定一个数组 trees&#xff0c;其中 trees[i] [xi, yi] 表示树在花园中的位置。 你被要求用最短长度的绳子把整个花园围起来&#xff0c;因为绳子很贵。只有把 所有的树都围起来&#xff0c;花园才围得很好。 返回恰好位于围栏周边的树木的坐标。 示例 1: 输入: points […

MySQL 的数据类型

1.整数类型 1.1 tinyint tinyint 为小整数类型&#xff0c;存储空间为1个字节&#xff08;8位&#xff09;&#xff0c;有符号范围-128 ~ 127&#xff0c;无符号范围 0 ~ 255,此类型通常在数据库中表示类型的字段&#xff0c;如某一字段 type 表示学科,其中 “type1” 表示语文…

实战篇:(二)React 创建项目并连接 MySQL 后台的实战教程

React 创建项目并连接 MySQL 后台的实战教程 一、项目概述 本篇博客将介绍如何使用 React 搭建前端项目&#xff0c;并通过 Node.js 和 MySQL 实现简单的后台数据连接。通过这个项目&#xff0c;你将掌握从前端到后端数据库的基础开发流程&#xff0c;适合初学者或正在项目实…

中国各大一线及二线省会城市程序员收入大比拼,看看你所在的城市的统计是否准确

在中国&#xff0c;程序员的收入因城市、经验、学历等因素而有所不同。本文将对一线及二线省会城市的程序员收入进行详细比较&#xff0c;帮助大家了解各地的薪资水平。 一线城市程序员收入 上海 上海作为中国的经济中心&#xff0c;程序员收入最高。根据最新数据&#xff…