空气质量仿真软件:CALPUFF (California PUFF Model)_(8).排放源数据处理

排放源数据处理

在使用CALPUFF进行空气质量仿真时,排放源数据的处理是至关重要的一步。排放源数据包括了各种污染源的排放量、位置、高度、排放速率等信息,这些数据的质量直接影响到仿真的准确性和可靠性。本节将详细介绍如何处理排放源数据,包括数据的准备、格式要求、输入方法以及一些常见的数据处理技巧。

1. 数据准备

在开始处理排放源数据之前,需要确保数据的完整性和准确性。排放源数据通常包括以下几个部分:

  • 排放源位置:经纬度坐标,单位为度。

  • 排放源高度:排放源的高度,单位为米。

  • 排放速率:单位时间内排放的污染物量,单位可以是克/秒、千克/小时等。

  • 排放源类型:点源、线源、面源或体源。

  • 排放时间:排放源的启动和停止时间。

  • 排放物种类:如SO2、NOx、PM10等。

2. 数据格式要求

CALPUFF接受的排放源数据格式为SOURCE.DAT。这个文件是一个文本文件,包含了一系列的排放源信息。文件的格式要求如下:

  • 文件头:文件的前几行是文件头,包含了一些基本信息,如文件名、数据单位等。

  • 数据行:每一行代表一个排放源,包含多个字段,字段之间用空格或逗号分隔。

一个典型的SOURCE.DAT文件示例如下:


# SOURCE.DAT - 排放源数据文件

# 单位:度, 米, 克/秒



# 源类型, 经度, 纬度, 高度, 排放速率, 排放时间, 污染物种类

POINT 120.123 30.456 100 0.5 202301010000 202301010100 SO2

LINE 120.123 30.456 120.789 30.123 100 1.0 202301010000 202301010200 NOx

AREA 120.123 30.456 120.789 30.123 100 2.0 202301010000 202301010300 PM10

VOLUME 120.123 30.456 120.789 30.123 100 3.0 202301010000 202301010400 CO

3. 输入方法

排放源数据可以通过多种方式输入到CALPUFF中,最常见的方式是通过文本文件直接读取。具体步骤如下:

  1. 创建SOURCE.DAT文件:使用文本编辑器创建一个包含排放源数据的文本文件。

  2. 设置输入文件路径:在CALPUFF的配置文件中指定SOURCE.DAT文件的路径。

  3. 运行仿真:启动CALPUFF仿真,读取并处理排放源数据。

以下是一个简单的Python脚本示例,用于生成SOURCE.DAT文件:


# 生成排放源数据文件的Python脚本



# 导入必要的库

import os



# 定义排放源数据

sources = [

    {"type": "POINT", "lon": 120.123, "lat": 30.456, "height": 100, "rate": 0.5, "start_time": "202301010000", "end_time": "202301010100", "pollutant": "SO2"},

    {"type": "LINE", "lon1": 120.123, "lat1": 30.456, "lon2": 120.789, "lat2": 30.123, "height": 100, "rate": 1.0, "start_time": "202301010000", "end_time": "202301010200", "pollutant": "NOx"},

    {"type": "AREA", "lon1": 120.123, "lat1": 30.456, "lon2": 120.789, "lat2": 30.123, "height": 100, "rate": 2.0, "start_time": "202301010000", "end_time": "202301010300", "pollutant": "PM10"},

    {"type": "VOLUME", "lon1": 120.123, "lat1": 30.456, "lon2": 120.789, "lat2": 30.123, "height": 100, "rate": 3.0, "start_time": "202301010000", "end_time": "202301010400", "pollutant": "CO"}

]



# 写入数据到文件

file_path = "SOURCE.DAT"

with open(file_path, "w") as file:

    file.write("# SOURCE.DAT - 排放源数据文件\n")

    file.write("# 单位:度, 米, 克/秒\n")

    for source in sources:

        if source["type"] == "POINT":

            file.write(f"POINT {source['lon']} {source['lat']} {source['height']} {source['rate']} {source['start_time']} {source['end_time']} {source['pollutant']}\n")

        elif source["type"] == "LINE":

            file.write(f"LINE {source['lon1']} {source['lat1']} {source['lon2']} {source['lat2']} {source['height']} {source['rate']} {source['start_time']} {source['end_time']} {source['pollutant']}\n")

        elif source["type"] == "AREA":

            file.write(f"AREA {source['lon1']} {source['lat1']} {source['lon2']} {source['lat2']} {source['height']} {source['rate']} {source['start_time']} {source['end_time']} {source['pollutant']}\n")

        elif source["type"] == "VOLUME":

            file.write(f"VOLUME {source['lon1']} {source['lat1']} {source['lon2']} {source['lat2']} {source['height']} {source['rate']} {source['start_time']} {source['end_time']} {source['pollutant']}\n")



# 检查文件是否生成

if os.path.exists(file_path):

    print(f"文件 {file_path} 生成成功")

else:

    print(f"文件 {file_path} 生成失败")

4. 常见的数据处理技巧

在实际应用中,排放源数据可能非常复杂,需要进行一些预处理和优化。以下是一些常见的数据处理技巧:

  • 数据验证:确保所有数据字段的格式和单位正确,避免因数据错误导致仿真失败。

  • 数据筛选:根据仿真需求筛选出特定时间段或特定类型的排放源。

  • 数据聚合:将多个相似的排放源合并为一个,以减少数据量和提高仿真效率。

  • 数据插值:对于缺失的排放数据,可以使用插值方法进行补全。

4.1 数据验证

数据验证是一个重要的步骤,可以使用Python脚本进行自动验证。以下是一个示例脚本,用于验证SOURCE.DAT文件中的数据格式:


# 数据验证脚本



# 导入必要的库

import os

import re



# 定义正则表达式模式

source_pattern = re.compile(r"^(POINT|LINE|AREA|VOLUME)\s+[-+]?\d*\.?\d+\s+[-+]?\d*\.?\d+\s+\d+\s+[-+]?\d*\.?\d+\s+\d{12}\s+\d{12}\s+[\w]+$")



# 读取文件并进行验证

file_path = "SOURCE.DAT"

with open(file_path, "r") as file:

    lines = file.readlines()



# 验证每一行数据

for i, line in enumerate(lines):

    if not source_pattern.match(line):

        print(f"第 {i+1} 行数据格式错误:{line.strip()}")



# 检查文件是否生成

if os.path.exists(file_path):

    print(f"文件 {file_path} 验证完成")

else:

    print(f"文件 {file_path} 不存在")

4.2 数据筛选

数据筛选可以根据特定条件选择符合要求的排放源。以下是一个示例脚本,用于筛选出特定时间段内的排放源数据:


# 数据筛选脚本



# 导入必要的库

import os

from datetime import datetime, timedelta



# 定义筛选条件

start_time = datetime.strptime("202301010000", "%Y%m%d%H%M")

end_time = datetime.strptime("202301010200", "%Y%m%d%H%M")



# 读取文件并进行筛选

file_path = "SOURCE.DAT"

output_file_path = "SELECTED_SOURCE.DAT"

with open(file_path, "r") as file, open(output_file_path, "w") as output_file:

    lines = file.readlines()

    output_file.write("# SELECTED_SOURCE.DAT - 筛选出的排放源数据文件\n")

    output_file.write("# 单位:度, 米, 克/秒\n")

    for line in lines:

        if line.startswith("#"):

            continue

        parts = line.split()

        source_start_time = datetime.strptime(parts[5], "%Y%m%d%H%M")

        source_end_time = datetime.strptime(parts[6], "%Y%m%d%H%M")

        if source_start_time <= end_time and source_end_time >= start_time:

            output_file.write(line)



# 检查输出文件是否生成

if os.path.exists(output_file_path):

    print(f"文件 {output_file_path} 生成成功")

else:

    print(f"文件 {output_file_path} 生成失败")

4.3 数据聚合

数据聚合可以将多个相似的排放源合并为一个,以减少数据量和提高仿真效率。以下是一个示例脚本,用于聚合点源数据:


# 数据聚合脚本



# 导入必要的库

import os

from collections import defaultdict



# 读取文件并进行聚合

file_path = "SOURCE.DAT"

output_file_path = "AGGREGATED_SOURCE.DAT"

with open(file_path, "r") as file, open(output_file_path, "w") as output_file:

    lines = file.readlines()

    output_file.write("# AGGREGATED_SOURCE.DAT - 聚合后的排放源数据文件\n")

    output_file.write("# 单位:度, 米, 克/秒\n")

    aggregated_sources = defaultdict(lambda: {"lon": 0, "lat": 0, "height": 0, "rate": 0, "start_time": "999999999999", "end_time": "000000000000", "pollutant": ""})



    for line in lines:

        if line.startswith("#"):

            continue

        parts = line.split()

        source_type = parts[0]

        if source_type == "POINT":

            lon = float(parts[1])

            lat = float(parts[2])

            height = int(parts[3])

            rate = float(parts[4])

            start_time = parts[5]

            end_time = parts[6]

            pollutant = parts[7]



            key = f"{lon:.3f} {lat:.3f} {height} {pollutant}"

            aggregated_sources[key]["lon"] += lon

            aggregated_sources[key]["lat"] += lat

            aggregated_sources[key]["height"] += height

            aggregated_sources[key]["rate"] += rate

            aggregated_sources[key]["start_time"] = min(aggregated_sources[key]["start_time"], start_time)

            aggregated_sources[key]["end_time"] = max(aggregated_sources[key]["end_time"], end_time)

            aggregated_sources[key]["pollutant"] = pollutant



    # 写入聚合后的数据

    for key, source in aggregated_sources.items():

        lon, lat, height, pollutant = key.split()

        output_file.write(f"POINT {source['lon']/source['rate']} {source['lat']/source['rate']} {source['height']} {source['rate']} {source['start_time']} {source['end_time']} {pollutant}\n")



# 检查输出文件是否生成

if os.path.exists(output_file_path):

    print(f"文件 {output_file_path} 生成成功")

else:

    print(f"文件 {output_file_path} 生成失败")

4.4 数据插值

数据插值可以用于补全缺失的排放数据。以下是一个示例脚本,用于对缺失的排放速率进行线性插值:


# 数据插值脚本



# 导入必要的库

import os

import pandas as pd

from datetime import datetime, timedelta



# 读取数据

file_path = "SOURCE.DAT"

data = pd.read_csv(file_path, delim_whitespace=True, skiprows=2, header=None, names=["type", "lon1", "lat1", "lon2", "lat2", "height", "rate", "start_time", "end_time", "pollutant"])



# 将时间字段转换为datetime类型

data["start_time"] = pd.to_datetime(data["start_time"], format="%Y%m%d%H%M")

data["end_time"] = pd.to_datetime(data["end_time"], format="%Y%m%d%H%M")



# 定义插值时间间隔

time_interval = timedelta(hours=1)



# 插值数据

interpolated_data = []

for index, row in data.iterrows():

    if row["type"] == "POINT":

        current_time = row["start_time"]

        while current_time < row["end_time"]:

            interpolated_data.append([row["type"], row["lon1"], row["lat1"], row["height"], row["rate"], current_time.strftime("%Y%m%d%H%M"), (current_time + time_interval).strftime("%Y%m%d%H%M"), row["pollutant"]])

            current_time += time_interval



# 创建DataFrame

interpolated_df = pd.DataFrame(interpolated_data, columns=["type", "lon1", "lat1", "height", "rate", "start_time", "end_time", "pollutant"])



# 写入插值后的数据

output_file_path = "INTERPOLATED_SOURCE.DAT"

interpolated_df.to_csv(output_file_path, sep=" ", index=False, header=False)



# 添加文件头

with open(output_file_path, "r+") as file:

    content = file.read()

    file.seek(0, 0)

    file.write("# INTERPOLATED_SOURCE.DAT - 插值后的排放源数据文件\n")

    file.write("# 单位:度, 米, 克/秒\n")

    file.write(content)



# 检查输出文件是否生成

if os.path.exists(output_file_path):

    print(f"文件 {output_file_path} 生成成功")

else:

    print(f"文件 {output_file_path} 生成失败")

5. 高级数据处理

除了基本的数据处理方法,CALPUFF还支持一些高级数据处理功能,如动态排放源、多时段排放源等。这些功能可以通过扩展SOURCE.DAT文件格式来实现。

5.1 动态排放源

动态排放源是指排放速率随时间变化的排放源。在SOURCE.DAT文件中,可以通过多行数据来表示一个排放源在不同时间段的排放速率。


# 动态排放源示例

POINT 120.123 30.456 100 0.5 202301010000 202301010100 SO2

POINT 120.123 30.456 100 1.0 202301010100 202301010200 SO2

POINT 120.123 30.456 100 1.5 202301010200 202301010300 SO2

5.2 多时段排放源

多时段排放源是指在多个不连续的时间段内有排放的源。可以通过在SOURCE.DAT文件中添加多行数据来表示不同时间段的排放源。


# 多时段排放源示例

POINT 120.123 30.456 100 0.5 202301010000 202301010100 SO2

POINT 120.123 30.456 100 1.0 202301010200 202301010300 SO2

POINT 120.123 30.456 100 1.5 202301010400 202301010500 SO2

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kkchenjj

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值