Писаный (1195951), страница 6
Текст из файла (страница 6)
В результате анализа зависимости качества прогнозов приземной температуры воздуха было установлено, что значения оценок качества значительно ухудшаются при переходе фактической среднесуточной температуры воздуха через отметку в -10 градусов Цельсия, после сего оправдываемость прогнозов падает во многих пунктах наблюдения ниже 50%, а средняя абсолютная погрешность превышает 4 градуса Цельсия.
При исследовании поведения средней систематической погрешности с учетом смены времени года было установлено различное поведение прогностической температуры осенью и весной, что может говорить о недочетах в описании численной модели, например, о некачественной параметризации подстилающей поверхности. Полученные в ходе работы статистические данные, таблицы и карты с оценками качества могут быть в дальнейшем использованы специалистами в области географии и климата для изучения и выявления новых закономерностей в изменении качества прогнозов численной модели.
Разработанный программный комплекс имеет ценность как средство для оценки качества работы численной модели прогноза погоды в рамках данной работы, так и в будущем для контроля качества прогнозов приземной температуры. Также существует возможность легко перенастроить инструменты для расчета других оценок качества или анализа других параметров прогноза. Это достигается путем разбиения программ на отдельные инструменты и функциональной реализации алгоритма их работы.
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1 Наставление по краткосрочным прогнозам погоды общего назначения (РД 52. 27. 724−2009). – Обнинск: ИГ-СОЦИН, 2009. – 66 с.
2 Вельтищев Н.Ф. Информация о моделях общего пользования ММ5 и WRF. – Москва, 2005. –100 с.
3 Романский С.О. Краткосрочный численный прогноз погоды высокого пространственного разрешения по Владивостоку на базе модели WRF-ARW / С.О. Романский, Е.М Вербицкая // Вестник ДВО РАН. – 2014. – №5 – c. 48-57
2 Вербицкая Е.М. Среднесрочный прогноз элементов и явлений погоды для станций Дальневосточного региона России. – Санкт-Петербург: Гидрометеоиздат, 2003. – 148 с.
5 Саммерфильд, М. Python на практике. Создание качественных программ с использованием параллелизма, библиотек и паттернов / М. Саммерфильд. – М.: ДМК Пресс, 2014. – 987 c.
ПРИЛОЖЕНИЕ А
Код разработанных программных инструментов
Инструмент для расчетов оценок качества прогнозов
# coding: utf-8
from ConfigParser import RawConfigParser as ConfigParser
from sys import stderr
from os import listdir
def reduce_date(reversed_date):
y, m, d = [int(x) for x in reversed_date.split('.')]
d -= 1
if d == 0:
d = 31
m -= 1
if m == 0:
m = 12
y -= 1
if m in [4, 6, 9, 11]:
d -= 1
if m == 2:
leap = y%4 == 0 and y%100 != 0 or y%400 == 0
d = {True: 29, False: 28}[leap]
if m < 10:
m = '0' + str(m)
if d < 10:
d = '0' + str(d)
return '.'.join([str(x) for x in [y,m,d]])
def revert_date(date):
return '.'.join(date.strip().split('.')[::-1])
def belongs_to_season(date, season):
number_of_periods = (len(season)-1)/2
res = False
for i in range(number_of_periods):
res = res or (date >= season[1+2*i] and date <= season[1+2*i+1])
return res
cp = ConfigParser()
cp.readfp(open('config'))
program_data = cp.get('Common', 'PreProcessedDataDir')
output_dir = cp.get('Common', 'OutputDir')
seasons = cp.get('SeasonData', 'seasons')
seasons = seasons.strip().split('(')[1:]
seasons = [x.split(')')[0] for x in seasons]
seasons = [[y.strip() for y in x.split(';')] for x in seasons]
#Разворачиваем даты для удобного сравнения
seasons = [[x[0]] + [revert_date(y) for y in x[1:]] for x in seasons]
intervals = cp.get('SeasonData', 'intervals')
intervals = intervals.strip().split('(')[1:]
intervals = [x.split(')')[0] for x in intervals]
intervals = [[y.strip() for y in x.split(';')] for x in intervals]
for interval in intervals:
if len(interval[0]) == 0:
interval[0] = -200
else:
interval[0] = float(interval[0])
if len(interval[1]) == 0:
interval[1] = 200
else:
interval[1] = float(interval[1])
f = open(program_data + '/point_headers.txt')
point_headers = [x.strip() for x in f.read().split('\n')]
point_headers = filter(lambda x: len(x) > 0, point_headers)
f.close()
progressbar_iter = [0, len(point_headers)]
dst_file = open(output_dir + '/by_seasons.txt', 'w')
for header in point_headers:
stderr.write('\rProcessed %d of %d files' % tuple(progressbar_iter))
progressbar_iter[0] += 1
pointnum = header.split(' ')[0]
src_file = open(program_data + '/' + pointnum + '.txt')
dst_file.write("###############################################################################################\n")
dst_file.write(header + '\n')
#Читаем файл
lines = [x.strip() for x in src_file.read().split('\n')]
lines = filter(lambda x: len(x) > 0, lines)
#Отбираем строки, где есть прогноз и факт
lines = [x.split(' ') for x in lines]
lines = [filter(lambda x: len(x) > 0, y) for y in lines]
lines = filter(lambda x: len(x) == 4, lines)
lines = [[revert_date(x[0]), x[1], float(x[2]), float(x[3])] for x in lines]
#Группируем по датам
by_dates = {x[0]: [] for x in lines}
for line in lines:
by_dates[line[0]] += [line[1:]]
lines = None
#Вставляем 24 заблаговременность предыдущего дня, дублируя 00 срок текущего дня
for date in by_dates.keys():
if by_dates[date][0][0] != '00:00':
continue
new_date = reduce_date(date)
if not(new_date in by_dates):
by_dates[new_date] = []
new_elem = ['24:00'] + by_dates[date][0][1:]
by_dates[new_date] += [new_elem]
#Возвращаем список и сортируем дни
by_dates = [[key, by_dates[key]] for key in by_dates.keys()]
by_dates.sort()
#Отбираем те, у которых теперь 9 сроков, чтобы иметь полную инфу о среднесуточной температуре и об ошибке
#print len(by_dates)
by_dates = filter(lambda x: len(x[1]) == 9, by_dates)
#print len(by_dates)
#Считаем среднесуточные темературы
for date in by_dates:
temp = reduce(lambda a,x: a+x, [x[1] for x in date[1][:9]])
temp /= 9.0
date += [temp]
#Считаем ошибки
for date in by_dates:
for srok in date[1]:
ar = srok[2] - srok[1]
ab = abs(ar)
srok += [ar, ab]
#Отбираем по нужным сезонам
for season in seasons:
dst_file.write("-----------------------------------------------------------------------------------------------\n")
dst_file.write("Период: %s" % season[0] + '\n')
dst_file.write("Интервал N E Eabs P1 % P2 % P3 % P3.5 % P5 % P(>5)%\n")
by_season = filter(lambda x: belongs_to_season(x[0], season), by_dates)
#Отбираем по нужным интервалам
for interval in intervals:
by_interval = filter(lambda x: x[2] >= interval[0] and x[2] <= interval[1], by_season)
interval_name = ''
if interval[0] > -200:
interval_name += 'От %d' % interval[0]
if interval[1] < 200:
interval_name += ' До %d' % interval[1]
interval_name = interval_name.strip()
if len(unicode(interval_name, 'utf-8')) < 15:
interval_name += ' '*(15 - len(unicode(interval_name, 'utf-8')))
data_to_print = interval_name
if len(by_interval) > 0:
errors = reduce(lambda a,x: a+x, [y[1] for y in by_interval])
errors = [x[3:] for x in errors]
N = len(errors)
Ear = reduce(lambda a,x: a+x, [y[0] for y in errors])/N
Eabs = reduce(lambda a,x: a+x, [y[1] for y in errors])/N
P1 = len(filter(lambda x: x < 1, [y[1] for y in errors]))*100.0/N
P2 = len(filter(lambda x: x < 2, [y[1] for y in errors]))*100.0/N
P3 = len(filter(lambda x: x < 3, [y[1] for y in errors]))*100.0/N
P35 = len(filter(lambda x: x < 3.5, [y[1] for y in errors]))*100.0/N
P5 = len(filter(lambda x: x < 5, [y[1] for y in errors]))*100.0/N
Pg5 = len(filter(lambda x: x >= 5, [y[1] for y in errors]))*100.0/N
data_to_print = (interval_name, N, Ear, Eabs, P1, P2, P3, P35, P5, Pg5)
dst_file.write("%s %5d %5.1f %5.1f %4.0f %4.0f %4.0f %4.0f %4.0f %4.0f\n" % data_to_print)
else:
dst_file.write("%s 0 - - - - - - - -\n" % data_to_print)
stderr.write('\rProcessed %d of %d files\n' % tuple(progressbar_iter))
dst_file.close()
Инструмент для нанесения данных на карту
#-*- coding:utf-8 -*-
#from __future__ import unicode_literals
import matplotlib
matplotlib.use('Agg')
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from pylab import *
from mpl_toolkits.basemap import Basemap
import numpy as np
import os
import time
import pickle
import threading
from multiprocessing import Pool, cpu_count
import subprocess
import gc
from scipy.interpolate import griddata
import scipy.ndimage
import matplotlib.patches as mpatches
import matplotlib.font_manager as font_manager
from sys import argv
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from ConfigParser import RawConfigParser as ConfigParser
from sys import stderr
from os import system
# размеры шрифтов
TITLE_SIZE=28
BAR_SIZE=16
LEGEND_SIZE=14
def generateMap(lat, lon, ax):
bMap = Basemap(projection='stere', width=5500000,height=4000000,resolution='i', lat_0=(lat[0]+lat[1])/2, lon_0=(lon[0]+lon[1])/2, ax=ax)
return bMap
# Создаём изображение
fig = plt.figure(figsize=(18, 18), dpi=70, facecolor='w', edgecolor='k')
def createMap(lon, lat, cmaps, cnorms, ticks):
# Создаём области под карты
axP3 = plt.axes([0,0,1,1])
axEabs = plt.axes([0,0.8,1,1])
axEar = plt.axes([0,1.6,1,1])
plots = [[axEabs],[axEar],[axP3]]
# Наносим карты
for plot in plots:
bMap = generateMap(lat, lon, plot[0])
plot += [bMap]
bMap.drawcountries(linewidth=1.5, color='purple')
bMap.fillcontinents(color='#FFFCC4', zorder = 0)
bMap.drawcoastlines(linewidth=0.75)
bMap.drawparallels(np.arange(-90., 120., 10.), labels=[1,0,0,0], color="k", fontsize=LEGEND_SIZE, linewidth=1, labelstyle='+/-')
bMap.drawmeridians(np.arange(0., 420., 10.), labels=[0,0,0,1], color="k", fontsize=LEGEND_SIZE, linewidth=1, labelstyle='+/-')
# Создаем шкалу
for i in range(0, len(plots)):
axins = inset_axes(plots[i][0], width="2%", height="60%", loc=4)
cb = mpl.colorbar.ColorbarBase(axins, cmap=cmaps[i], norm=cnorms[i], ticks=ticks[i], orientation='vertical')
# Пишем заголовки
for i in range(0, len(plots)):
plots[i][0].set_title(['Eabs', 'Ear', 'P3'][i], fontsize=TITLE_SIZE)
return plots
# Карта
def plotMap(map_templates, title, data, cmaps, cnorms, filename, legend_sizes):
#Запоминаем точки, чтобы потом их стереть
to_remove = []
# Рисуем данные
for point in data:
# Перебираем имеющиеся данные
for i in range(1, len(point)):
xx,yy = map_templates[i-1][1](float(point[0][1]), float(point[0][0]))
# Вычисляем цвет точки
point_color = cmaps[i-1](cnorms[i-1](point[i]))
l, = map_templates[i-1][0].plot(xx, yy, 'o', markersize=7)
to_remove += [l]
l.set_markerfacecolor(point_color)
l.set_color(point_color)
if abs(float(point[0][1]) - 158) < 1 and abs(float(point[0][0]) - 53) < 1:
if abs(point[0][0] - 53.083) < 0.01:
dy = 0.25
if abs(point[0][1] - 158.3) < 0.01:
dy = -dy
xx,yy = map_templates[i-1][1](float(point[0][1])-0.1, float(point[0][0])+dy)
l = map_templates[i-1][0].text(xx-10.0, yy+0.5, '%.0f'%point[i], color='black', fontsize=legend_sizes[i-1])
to_remove += [l]
fig.suptitle(title, fontsize=TITLE_SIZE, x = 0.5, y = 2.55)
# Сохраняем рисунок
plt.savefig(filename, bbox_inches='tight', dpi=70)
#plt.close(fig)
for l in to_remove:
l.remove()
# main
cp = ConfigParser()
cp.readfp(open('config'))
program_data = cp.get('Common', 'PreProcessedDataDir')
output_dir = cp.get('Common', 'OutputDir')
#points = {x[0].strip() : x[1:] for x in points}















