get_many_data_all_cathment.py 14.5 KB
import urllib.request
import json
import os
import datetime
from imageio import imread
import cv2
import numpy as np
import loca_data
import duamel_model
import matplotlib.pyplot as plt
import sher_duam_class


png_path = r"d:\PYTHON\tests\test1\png"

lenght_lan = 79497.3714882
lenght_lon = 111162.6
base_pixel_len = 152.8740566
str_limiter = '||'

d1plan_g = base_pixel_len / lenght_lan
d1plon_g = base_pixel_len / lenght_lon
x286lon = 38.72287
x286lan = 44.417242


base_lon = x286lon - (128 * d1plon_g)
min_lon = x286lon - (128 * d1plon_g)
max_lon = x286lon + (128 * d1plon_g)

base_lan = x286lan + (128 * d1plan_g)
min_lan = x286lan - (128 * d1plan_g)
max_lan = x286lan + (128 * d1plan_g)

pol_store = []
prec_meas = []

duamel = duamel_model.DumlRiverModel(_k_n=1.0, _k_korr=25.0, _res_add_val=20.0, _dmi_up_per=1.0, _dmi_down_per=20.0)
duamelk1 = duamel_model.DumlRiverModel(_k_n=1.65, _k_korr=25.0, _res_add_val=25.0, _dmi_up_per=0.00001, _dmi_down_per=20.0)
flow_rate = duamel_model.CatchmentArea(_capacity=22.2, _in_filter=1.0, _out_filter=0.09)
flow_rate1 = duamel_model.CatchmentArea(_capacity=100.0, _in_filter=2.0, _out_filter=0.09)
level_calc = duamel_model.RiverCrossSection(_left_slope=5.0, _bottom=18.0, _right_slope=5.0, _max_h=3.6, _zero_bsv=-1.06, _n_roughness=0.035, _i_bias=0.00244)
sher_duam = sher_duam_class.TestSherDuamel(_k_up=0.7, _k_down=25.0, _k_multy=120.0, _k_addit=40.0, _zero_level=2.20)

# Генерировать измерители всех типов
def GenerateMeasurements():

    # Точки для полигонов
    result = []
    all_result = []

    # Получение координат полигона водосбора Джубги
    pcs = loca_data.GetGeoCoordPolygon()

    # Последняя запись - для отбрасывания дублей пикселей
    p_last = dict(x = -1.0, y = 0.0)

    # Получаем список точек полигона
    for pc in pcs:
        p = GetMeas(pc[0], pc[1], pc[2], pc[3])

        if p_last['x'] == -1.0:
            p_last['x'] = p['x']
            p_last['y'] = p['y']
            all_result.append(p)
        else:
            if p_last['x'] != p['x'] and p_last['y'] != p['y']:
                all_result.append(p)

            p_last['x'] = p['x']
            p_last['y'] = p['y']

    result.append(GetMeas(0, 'TEST_00', x286lan, x286lon))
    result.append(GetMeas(1, 'TEST_01', 44.3251277777778, 38.6788694444444))
    result.append(GetMeas(2, 'TEST_02', 44.3727555555556, 38.7005))
    result.append(GetMeas(3, 'TEST_03', 44.4186305555556, 38.6651361111111))
    result.append(GetMeas(4, 'TEST_04', 44.4545888888889, 38.6328638888889))
    result.append(GetMeas(5, 'TEST_05', 44.4508222222222, 38.6833333333333))
    result.append(GetMeas(6, 'TEST_06', 44.4329277777778, 38.7327722222222))
    result.append(GetMeas(7, 'TEST_07', 44.4106166666667, 38.7633277777778))
    result.append(GetMeas(8, 'TEST_08', 44.3846138888889, 38.7533722222222))
    result.append(GetMeas(9, 'TEST_09', 44.3416583333333, 38.735175))

    prec_meas.append(GetMeas(5, 'X286|s0_d0', x286lan+0,         x286lon-0))

    pol_store.append(GeneratePolygons(all_result, 0, "All"))
    #pol_store.append(GeneratePolygons([result[0], result[3], result[4], result[5], result[6]], 1, "Verh"))
    #pol_store.append(GeneratePolygons([result[0], result[6], result[7], result[8], result[9], result[1], result[2]], 2, "Nige_Polkovnichego"))

    return

# получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы
def GetMeas(_number, _name, _lan, _lon):
    if _lan <= min_lan or _lan >= max_lan:
        print("MeasUnit named {} have not current lan ({})".format(_name, _lan))
        return None
    if _lon <= min_lon or _lon >= max_lon:
        print("MeasUnit named {} have not current lon ({})".format(_name, _lon))
        return None

    lan_delta = _lan - base_lan
    lon_delta = _lon - base_lon

    y_delta = lan_delta * lenght_lan
    x_delta = lon_delta * lenght_lon

    my = y_delta // base_pixel_len
    mx = x_delta // base_pixel_len

    result = dict(number = _number, name = _name, x = abs(mx), y = abs(my))
    return result

# Получить осадки по значению dbZ
def GetPrecByDBZ_2(_dbz):
    result = 0

    if _dbz == 0 or _dbz > 127:
        return result

    step1 = (_dbz - 32) / 10
    step2 = 10 ** step1
    step3 = step2 / 200
    step4 = step3 ** 0.625
    result = step4
    return result

# Сгенерировать полигон по набору геокоординат
def GeneratePolygons(_meas_list, _number, _name):
    # Максимальные значения координат Х и У для полигона
    max_x = 0
    max_y = 0
    min_x = 256
    min_y = 256

    #Временный полигон
    tmp_pol = []

    # Перебрать измерители последовательно и сформировать полигон как набор пар (х, у) плюс данные о границах полигона (прямоугольных)
    for imeas in _meas_list:
        mx =imeas["x"]
        my = imeas["y"]
        # Ищем прямоугольные границы полигона
        if mx > max_x:
            max_x = mx
        if my > max_y:
            max_y = my
        if mx < min_x:
            min_x = mx
        if my < min_y:
            min_y = my
        tmp_pol.append((mx, my))

    result = dict(number = _number, name = _name, max_x = max_x, max_y = max_y, min_x = min_x, min_y = min_y, pol = tmp_pol)
    result["pol"] = tmp_pol
    return result

# Получить "обрезанную" матрицу по полигону
def GetCuttedMatrix(_image, _mpolygon):
    matrix = _mpolygon["pol"]
    max_x = int(_mpolygon["max_x"])
    max_y = int(_mpolygon["max_y"])
    min_x = int(_mpolygon["min_x"])
    min_y = int(_mpolygon["min_y"])

    mask = np.zeros(_image.shape, dtype=np.uint8)
    roi_corners = np.array([matrix], dtype=np.int32)
    channel_count = _image.shape[2]  # i.e. 3 or 4 depending on your image
    ignore_mask_color = (255,)*channel_count
    cv2.fillPoly(mask, roi_corners, ignore_mask_color)
    masked_image = cv2.bitwise_and(_image, mask)
    masked_image = masked_image[min_y:max_y, min_x:max_x]
    return masked_image


# Получаем все файлы из директории с сохранёнными изображениями
png_files = os.listdir(png_path)
print(png_files)
print("Lan border = {} - {}".format(min_lan, max_lan))
print("Lon border = {} - {}".format(min_lon, max_lon))

# Сформировать массив "матрица картинки-время" (время из названия файла)
store = []
for png_f in png_files:
    dt_value = png_f.replace('dj_286m_', '').replace('.png', '')
    dt_value = int(dt_value)
    dt_value = datetime.datetime.fromtimestamp(dt_value)
    date_diff = datetime.timedelta(hours=0)
    dt_value = dt_value + date_diff
    file_data = imread(png_path + '\\' + png_f)
    st_unit = dict(
        datetime = dt_value,
        matrix = file_data
    )

    store.append(st_unit)

# Генерируем измерители
GenerateMeasurements()

# Формируем данные
main_data = "Дата||АГК-286М||АГК-34||РАД-286М||RAD286(cor)||Сумма ВСЕГО||Сумма ВСЕГО(кор)||Сумма ВСЕГО ОБ||Сумма ВСЕГО ОБ(кор)||Flow||Duamel||DuamLevel||\n"

# Последниё интервал расчёта
last_datetime = store[0]["datetime"]

# Дельта (служебная) между интервалами расчёта
dt =  datetime.timedelta(minutes=10)

# Интервал времени
datetime_min = datetime.datetime(2020, 1, 29, 22, 50, 0)
datetime_max = datetime.datetime(2020, 2, 4, 15, 40, 0)

# Реальные 286М и 34
real286 = loca_data.GetPrec286M()
real34 = loca_data.GetLevel34()

dtcounter = -1

# Для графиков
mas_x = [] #time
mas_real = [] #real water level
mas_duam = [] #duamel water level
mas_duam1 = [] #duamel water level
mas_sher_duam = [] #дюамель от шержукова
mas_wvol = [] #water volume

# Пробегаемся по всем датам в хранилище реальных осадков
for rdata_key in real286.keys():

    dtcounter = dtcounter + 1
    mas_x.append(dtcounter)

    koef_multy_re_d_rad = 1
    koef_addit_re_m_rad = 0
    prec_data = None
    lmatrix = None
    ldatetime = rdata_key
    print(ldatetime)
    local_data = ""
    local_data += ldatetime.__str__() + str_limiter

    # 0. Осадки реальные
    real_prec = real286[rdata_key]
    local_data += real_prec.__str__() + str_limiter

    # 0.1 Уровень реальный
    real_level = real34[rdata_key]
    local_data += real_level.__str__() + str_limiter
    mas_real.append(real_level)

    for imgmatrix in store:
        if imgmatrix["datetime"] == rdata_key:
            lmatrix = imgmatrix["matrix"]

    if lmatrix is None:
        local_data += "0||0||0||0||"
        rain_corr = real_prec
        flow = flow_rate.calc_surface_flow(rain_corr)
        flow1 = flow_rate1.calc_surface_flow(rain_corr)

        duam_value = duamel.model_step(dtcounter, flow)
        duam_valk1 = duamelk1.model_step(dtcounter, flow)

        wlevel = level_calc.bs_water_level(duam_value)
        wlevel1 = level_calc.bs_water_level(duam_valk1)

        mas_duam.append(wlevel)
        mas_duam1.append(wlevel1)

        test_sher_level = sher_duam.CalculateLevel(rain_corr, dtcounter)
        mas_sher_duam.append(test_sher_level)

        mas_wvol.append(0.0)

        local_data += flow.__str__() + str_limiter
        local_data += duam_value.__str__() + str_limiter
        local_data += wlevel.__str__() + str_limiter

        main_data += local_data + "\n"
        continue

    # 1. Расчёт осадков по координатам
    # Формируем для каждого измерителя оасдки в точке, согласно его прямоугольным координатам относительно картинки
    mes = prec_meas[0]
    y = int(mes["y"])
    x = int(mes["x"])
    value = lmatrix[y][x][0]
    dmrl_prec = GetPrecByDBZ_2(value)
    dmrl_prec = dmrl_prec / 6
    local_data += dmrl_prec.__str__() + str_limiter

    # 1.1 Считаем коэффициенты
    if dmrl_prec > 0 and real_prec > 0:
        koef_multy_re_d_rad = real_prec / dmrl_prec
        koef_addit_re_m_rad = 0
    elif dmrl_prec == 0 and real_prec > 0:
        koef_multy_re_d_rad = 1
        koef_addit_re_m_rad = real_prec - dmrl_prec
    elif dmrl_prec > 0 and real_prec == 0:
        koef_multy_re_d_rad = 1
        koef_addit_re_m_rad = 0

    # 1.2 Считаем осадки после корректировки
    dmrl_prec_cor = (dmrl_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad
    local_data += dmrl_prec_cor.__str__() + str_limiter

    # 2. Расчет площадей и осадков на площадях

    for pol in pol_store:
        masked_image = GetCuttedMatrix(lmatrix, pol)
        sum_prec = 0
        sum_squere = 0
        sum_prec_cor = 0
        vol_water = 0
        vol_water_cor = 0
        for yy in masked_image:
                for xx in yy:
                    lm_value = xx[0]
                    m_prec = GetPrecByDBZ_2(lm_value)
                    m_prec = m_prec / 6

                    if m_prec > 0:
                        sum_squere += 1

                    sum_prec += m_prec

                    m_prec_cor = ((m_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad)
                    sum_prec_cor = sum_prec_cor + m_prec_cor

                    vol_local = base_pixel_len * base_pixel_len * 1/1000 * m_prec
                    vol_water += vol_local

                    vol_local_cor = base_pixel_len * base_pixel_len * 1/1000 * m_prec_cor
                    vol_water_cor += vol_local_cor


        local_data += sum_prec.__str__() + str_limiter
        local_data += sum_prec_cor.__str__() + str_limiter
        local_data += vol_water.__str__() + str_limiter
        local_data += vol_water_cor.__str__() + str_limiter

        rain_corr = vol_water * 0.0000099471691 * 8
        mas_wvol.append(rain_corr)

        flow = flow_rate.calc_surface_flow(rain_corr)
        flow1 = flow_rate1.calc_surface_flow(rain_corr)

        duam_value = duamel.model_step(dtcounter, flow)
        duam_valk1 = duamelk1.model_step(dtcounter, flow)

        wlevel = level_calc.bs_water_level(duam_value)
        wlevel1 = level_calc.bs_water_level(duam_valk1)

        test_sher_level = sher_duam.CalculateLevel(flow1, dtcounter)

        mas_duam.append(wlevel)
        mas_duam1.append(wlevel1)
        mas_sher_duam.append(test_sher_level)

        local_data += flow.__str__() + str_limiter
        local_data += duam_value.__str__() + str_limiter
        local_data += wlevel.__str__() + str_limiter

        local_data += sum_squere.__str__() + str_limiter

        #local_data += sum_squere.__str__() + str_limiter

    # Вываливаем данные
    main_data += local_data + "\n"

# Заменяем временные разделители и прочие символы для правильного отобраежния в Эксель
main_data = main_data.replace("||", "\t")

# Пишем результат в текстовый файл
f = open('result.txt', 'w')
f.write(main_data)
f.close()

fig, ax = plt.subplots()

ax.plot(mas_x, mas_real, label = 'AGK-34')
ax.plot(mas_x, mas_duam, label = 'DUAM')
ax.plot(mas_x, mas_duam1, label = 'DUAM_2')
ax.plot(mas_x, mas_sher_duam, label = 'SHER_DUAM')

ax.legend()

plt.show()



"""
1. Для каждого измерителя ищем разницу в широте и долготе лот базовых координат
1.1 Проверяем на выход за предельные значения
2. По здначениям дельты и длинам градусов ищем разницу в метрах
3. По разнице в метрах и базовому размеру пикселя ищем нужный квадрат как количество целых делений дельты в метрах на базовую длину градуса
"""