add all files
Too many changes to show.
To preserve performance only 1000 of 1000+ files are displayed.
| 1 | { | ||
| 2 | // Use IntelliSense to learn about possible attributes. | ||
| 3 | // Hover to view descriptions of existing attributes. | ||
| 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
| 5 | "version": "0.2.0", | ||
| 6 | "configurations": [ | ||
| 7 | { | ||
| 8 | "name": "Python: Текущий файл", | ||
| 9 | "type": "python", | ||
| 10 | "request": "launch", | ||
| 11 | "program": "${file}", | ||
| 12 | "console": "integratedTerminal" | ||
| 13 | } | ||
| 14 | ] | ||
| 15 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | import time | ||
| 2 | import logging | ||
| 3 | import pika | ||
| 4 | import json | ||
| 5 | import time | ||
| 6 | import datetime | ||
| 7 | import pytz | ||
| 8 | |||
| 9 | from threading import Thread | ||
| 10 | from queue import Queue, Empty | ||
| 11 | from ocm_fwk.ocm_mq import OcmMqBase | ||
| 12 | |||
| 13 | import config as cfg | ||
| 14 | |||
| 15 | ''' | ||
| 16 | class MyJSONEncoder(json.JSONEncoder): | ||
| 17 | #Override the default method | ||
| 18 | def default(self, obj): | ||
| 19 | if isinstance(obj, (datetime.date, datetime.datetime)): | ||
| 20 | return obj.replace(tzinfo=datetime.timezone.utc).isoformat() | ||
| 21 | if isinstance(obj, np.ndarray): | ||
| 22 | return obj.tolist() | ||
| 23 | ''' | ||
| 24 | |||
| 25 | class test_cons(OcmMqBase): | ||
| 26 | |||
| 27 | def __init__(self, settings, consumer_queue=None, consumer_routing_key=None, consume_only_routing_key=True, | ||
| 28 | message_ttl_ms=None): | ||
| 29 | super(test_cons, self).__init__(settings) | ||
| 30 | self.logger = logging.getLogger(__name__) | ||
| 31 | |||
| 32 | if consumer_queue is None: | ||
| 33 | raise TypeError | ||
| 34 | if consumer_routing_key is None: | ||
| 35 | raise TypeError | ||
| 36 | |||
| 37 | self.consumer_queue = consumer_queue | ||
| 38 | self.consumer_routing_key = consumer_routing_key | ||
| 39 | self.consume_only_routing_key = consume_only_routing_key | ||
| 40 | self.message_ttl_ms = message_ttl_ms | ||
| 41 | |||
| 42 | self._loop_thread = Thread(target=self._main_loop) | ||
| 43 | self._stop_flag = False | ||
| 44 | |||
| 45 | self.mms_main_query = Queue() | ||
| 46 | |||
| 47 | def consume(self, routing_key, message_object): | ||
| 48 | self.mms_main_query.put(message_object) | ||
| 49 | print("{} -> consume bu rout {} messege :{}".format(datetime.datetime.now(), routing_key, message_object)) | ||
| 50 | return True | ||
| 51 | |||
| 52 | def get_lazy_data(self): | ||
| 53 | result = [] | ||
| 54 | while self.mms_main_query.qsize() != 0: | ||
| 55 | result.append(self.mms_main_query.get()) | ||
| 56 | return result | ||
| 57 | |||
| 58 | def _consumer_callback(self, ch, method, properties, body): | ||
| 59 | # проверка правильности подписки на routing_key | ||
| 60 | if self.consume_only_routing_key: | ||
| 61 | if isinstance(self.consumer_routing_key, str): # если routing key - одна строка | ||
| 62 | if self.consumer_routing_key != method.routing_key: | ||
| 63 | # сообщение не может быть обработано и посылать его повторно не нужно | ||
| 64 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False) | ||
| 65 | self.logger.warning('MQ: routing key({}) not proper'.format(method.routing_key)) | ||
| 66 | return | ||
| 67 | elif isinstance(self.consumer_routing_key, tuple): # если routing key - кортеж строк | ||
| 68 | if method.routing_key not in self.consumer_routing_key: | ||
| 69 | # сообщение не может быть обработано и посылать его повторно не нужно | ||
| 70 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False) | ||
| 71 | self.logger.warning('MQ: routing key({}) not proper'.format(method.routing_key)) | ||
| 72 | return | ||
| 73 | else: | ||
| 74 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False) | ||
| 75 | self.logger.warning('MQ: routing key has not proper type') | ||
| 76 | return | ||
| 77 | |||
| 78 | # преобразование сообщения в нативный объект | ||
| 79 | try: | ||
| 80 | obj = json.loads(body.decode('utf-8')) | ||
| 81 | except Exception: | ||
| 82 | self.logger.exception("MQ: json conversion error") | ||
| 83 | # сообщение не может быть обработано и посылать его повторно не нужно | ||
| 84 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False) | ||
| 85 | return | ||
| 86 | |||
| 87 | # callback может вернуть | ||
| 88 | # None - простым вызовом return или по завершению кода обработчика, то же самое, что False | ||
| 89 | # True - сообщение обработано, можно посылать ack - удаляет сообщение из очереди | ||
| 90 | # False - сообщение не обработано, нужно его отправить обратно в очередь - послать nack(requeue=True) | ||
| 91 | ack = None | ||
| 92 | try: | ||
| 93 | ack = self.consume(method.routing_key, obj) | ||
| 94 | except Exception: | ||
| 95 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False) | ||
| 96 | self.logger.exception("MQ: message not consumed") | ||
| 97 | raise | ||
| 98 | |||
| 99 | # если callback не возвратил логический тип, значит ack - False | ||
| 100 | if ack is None: | ||
| 101 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=True) | ||
| 102 | elif ack: | ||
| 103 | ch.basic_ack(delivery_tag=method.delivery_tag) | ||
| 104 | else: | ||
| 105 | ch.basic_nack(delivery_tag=method.delivery_tag, requeue=True) | ||
| 106 | |||
| 107 | def _main_loop(self): | ||
| 108 | while not self._stop_flag: | ||
| 109 | connection = None | ||
| 110 | ch_consumer = None | ||
| 111 | try: | ||
| 112 | connection = pika.BlockingConnection(self.parameters) | ||
| 113 | ch_consumer = connection.channel() | ||
| 114 | ch_consumer.basic_qos(prefetch_count=100) # todo: вынести в настройки | ||
| 115 | |||
| 116 | # определение очереди сообщений, в случае отсутствия, будет создана | ||
| 117 | if self.message_ttl_ms is not None: | ||
| 118 | queue = ch_consumer.queue_declare( | ||
| 119 | queue=self.consumer_queue, | ||
| 120 | durable=True, | ||
| 121 | exclusive=False, | ||
| 122 | arguments={'x-message-ttl': self.message_ttl_ms, }, | ||
| 123 | ).method.queue | ||
| 124 | else: | ||
| 125 | queue = ch_consumer.queue_declare( | ||
| 126 | queue=self.consumer_queue, | ||
| 127 | durable=True, | ||
| 128 | exclusive=False, | ||
| 129 | ).method.queue | ||
| 130 | |||
| 131 | # привязка к очереди | ||
| 132 | if isinstance(self.consumer_routing_key, str): # если routing key - одна строка | ||
| 133 | ch_consumer.queue_bind( | ||
| 134 | exchange=self.EXCHANGE, | ||
| 135 | queue=queue, | ||
| 136 | routing_key=self.consumer_routing_key, | ||
| 137 | ) | ||
| 138 | elif isinstance(self.consumer_routing_key, tuple): # если routing key - кортеж строк | ||
| 139 | for key in self.consumer_routing_key: | ||
| 140 | ch_consumer.queue_bind( | ||
| 141 | exchange=self.EXCHANGE, | ||
| 142 | queue=queue, | ||
| 143 | routing_key=key | ||
| 144 | ) | ||
| 145 | else: | ||
| 146 | raise TypeError | ||
| 147 | |||
| 148 | # настройка обработчика получения сообщений | ||
| 149 | ch_consumer.basic_consume( | ||
| 150 | consumer_callback=self._consumer_callback, | ||
| 151 | queue=queue, | ||
| 152 | no_ack=False, | ||
| 153 | consumer_tag="ocm_mq_consumer" | ||
| 154 | ) | ||
| 155 | |||
| 156 | self.consumer_queue = queue | ||
| 157 | |||
| 158 | # блокирующий вызов ожидания входящих сообщений | ||
| 159 | try: | ||
| 160 | ch_consumer.start_consuming() | ||
| 161 | except: | ||
| 162 | ch_consumer.stop_consuming() | ||
| 163 | raise | ||
| 164 | |||
| 165 | except Exception: | ||
| 166 | self.logger.exception('mq consuming error, attempting to reconnect...') | ||
| 167 | finally: | ||
| 168 | try: | ||
| 169 | ch_consumer.close() | ||
| 170 | except: | ||
| 171 | pass | ||
| 172 | |||
| 173 | try: | ||
| 174 | connection.close() | ||
| 175 | except: | ||
| 176 | pass | ||
| 177 | |||
| 178 | time.sleep(self.RECONNECT_SLEEP_SECONDS) | ||
| 179 | |||
| 180 | try: | ||
| 181 | ch_consumer.close() | ||
| 182 | except: | ||
| 183 | pass | ||
| 184 | |||
| 185 | try: | ||
| 186 | connection.close() | ||
| 187 | except: | ||
| 188 | pass | ||
| 189 | |||
| 190 | def start(self): | ||
| 191 | """ Запуск подписчика для шины ОКМ """ | ||
| 192 | self._loop_thread.start() | ||
| 193 | |||
| 194 | def stop(self): | ||
| 195 | self._stop_flag = True | ||
| 196 | |||
| 197 | bus_TS = test_cons(cfg, "makeyev_L", "measurement.precipitation.*", consume_only_routing_key=False) | ||
| 198 | bus_LO = test_cons(cfg, "makeyev_C", "metering.rainfall", consume_only_routing_key=False) | ||
| 199 | print("begin...\n") | ||
| 200 | #cons.stop() | ||
| 201 | bus_LO.start() | ||
| 202 | bus_TS.start() | ||
| 203 | |||
| 204 | i = 0 | ||
| 205 | |||
| 206 | while i < 100: | ||
| 207 | i = i + 1 | ||
| 208 | print("Iterator={}\t\tdata:{}".format(i, bus_LO.get_lazy_data())) | ||
| 209 | print("Iterator={}\t\tdata:{}".format(i, bus_TS.get_lazy_data())) | ||
| 210 | time.sleep(30) | ||
| 211 | |||
| 212 | |||
| 213 | |||
| 214 | ''' | ||
| 215 | АГК-34Д uuid = "0efefaee-eada-446f-a2a0-f95acabfc0a7" Л | ||
| 216 | АГК-77Д uuid = "c3f0ecb7-c65e-4273-93a9-6f39a65dcd4a" Л | ||
| 217 | АГК-141 uuid = "83b895ae-3a21-4585-8289-e28da5d0cc43" C | ||
| 218 | АГК-040 uuid = "a6f44e50-ad18-4ee9-a6bb-ffae6a85d2a3" С | ||
| 219 | АГК-286 uuid = "33ce9a80-27df-41dd-8dbe-cf3ec918b4c2" С | ||
| 220 | ''' | ||
| 221 |
| 1 | import time | ||
| 2 | import logging | ||
| 3 | import pika | ||
| 4 | import json | ||
| 5 | import datetime | ||
| 6 | import pytz | ||
| 7 | |||
| 8 | from threading import Thread | ||
| 9 | from queue import Queue, Empty | ||
| 10 | from ocm_fwk.ocm_mq import OcmMqBase, OcmMqBlockingPublisher | ||
| 11 | |||
| 12 | import config as cfg | ||
| 13 | |||
| 14 | pub = OcmMqBlockingPublisher(cfg) | ||
| 15 | pub.publish("rk_1", 123) | ||
| 16 | pub.publish("rk_1", 666) | ||
| 17 | pub.publish("rk_1", 999) | ||
| 18 | |||
| 19 |
| 1 | #user_db_name = "web_forecast_7" | ||
| 2 | user_db_name = "qwer" | ||
| 3 | db_postgres_connection = dict(host="localhost",database=user_db_name, user="postgres", password="postgres") | ||
| 4 | redis_connection = dict(host='localhost', port=6379, db=0, password=None) | ||
| 5 | OCM_MQ = dict( | ||
| 6 | HOST = 'evolution.emercit.com', | ||
| 7 | PORT = 5672, | ||
| 8 | VIRTUAL_HOST = 'ocm', | ||
| 9 | EXCHANGE = 'monitoring', | ||
| 10 | USER = 'emercit', | ||
| 11 | PASSWORD = 'xfnLAW5pff3RpNFh') |
| 1 | Дата АГК-286М АГК-34 РАД-286М | ||
| 2 | 29.01.2020 22:50 0 -0,10 0,000000 | ||
| 3 | 29.01.2020 23:00 0 -0,11 0,00000000 | ||
| 4 | 29.01.2020 23:10 0 -0,09 0,00000000 | ||
| 5 | 29.01.2020 23:20 0 -0,09 0,00000000 | ||
| 6 | 29.01.2020 23:30 0 -0,09 0,00000000 | ||
| 7 | 29.01.2020 23:40 0 -0,10 0,00000000 | ||
| 8 | 29.01.2020 23:50 0 -0,10 0,00000000 | ||
| 9 | 30.01.2020 0:00 0 -0,09 0,00000000 | ||
| 10 | 30.01.2020 0:10 0 -0,10 0,00000000 | ||
| 11 | 30.01.2020 0:20 0 -0,09 0,00000000 | ||
| 12 | 30.01.2020 0:30 0 -0,09 0,00000000 | ||
| 13 | 30.01.2020 0:40 0 -0,09 0,00000000 | ||
| 14 | 30.01.2020 0:50 0 -0,08 0,00000000 | ||
| 15 | 30.01.2020 1:00 0 -0,08 0,00000000 | ||
| 16 | 30.01.2020 1:10 0 -0,09 0,00000000 | ||
| 17 | 30.01.2020 1:20 0 -0,07 0,00000000 | ||
| 18 | 30.01.2020 1:30 0 -0,09 0,00000000 | ||
| 19 | 30.01.2020 1:40 0 -0,08 0,00000000 | ||
| 20 | 30.01.2020 1:50 0 -0,08 0,00000000 | ||
| 21 | 30.01.2020 2:00 0 -0,08 0,00000000 | ||
| 22 | 30.01.2020 2:10 0 -0,09 0,00000000 | ||
| 23 | 30.01.2020 2:20 0 -0,08 0,00000000 | ||
| 24 | 30.01.2020 2:30 0 -0,08 0,00000000 | ||
| 25 | 30.01.2020 2:40 0 -0,08 0,00000000 | ||
| 26 | 30.01.2020 2:50 0 -0,08 0,00000000 | ||
| 27 | 30.01.2020 3:00 0 -0,09 0,03417472 | ||
| 28 | 30.01.2020 3:10 0 -0,09 0,03417472 | ||
| 29 | 30.01.2020 3:20 0 -0,09 0,02959409 | ||
| 30 | 30.01.2020 3:30 0 -0,10 0,07017865 | ||
| 31 | 30.01.2020 3:40 0,3 -0,10 0,16641980 | ||
| 32 | 30.01.2020 3:50 0,1 -0,09 0,16641980 | ||
| 33 | 30.01.2020 4:00 0,5 -0,11 0,09358473 | ||
| 34 | 30.01.2020 4:10 0,5 -0,11 0,16641980 | ||
| 35 | 30.01.2020 4:20 0,8 -0,11 0,34174723 | ||
| 36 | 30.01.2020 4:30 0,2 -0,11 0,16641980 | ||
| 37 | 30.01.2020 4:40 0,7 -0,09 0,09358473 | ||
| 38 | 30.01.2020 4:50 0,3 -0,09 0,09358473 | ||
| 39 | 30.01.2020 5:00 0,1 -0,09 0,09358473 | ||
| 40 | 30.01.2020 5:10 0,1 -0,09 0,16641980 | ||
| 41 | 30.01.2020 5:20 0,1 -0,09 0,07017865 | ||
| 42 | 30.01.2020 5:30 0,1 -0,09 0,16641980 | ||
| 43 | 30.01.2020 5:40 0,1 -0,10 0,16641980 | ||
| 44 | 30.01.2020 5:50 0 -0,10 0,14411361 | ||
| 45 | 30.01.2020 6:00 0 -0,10 0,03417472 | ||
| 46 | 30.01.2020 6:10 0 -0,11 0,07017865 | ||
| 47 | 30.01.2020 6:20 0 -0,11 0,07017865 | ||
| 48 | 30.01.2020 6:30 0 -0,11 0,09358473 | ||
| 49 | 30.01.2020 6:40 0 -0,12 0,02959409 | ||
| 50 | 30.01.2020 6:50 0 -0,12 0,03417472 | ||
| 51 | 30.01.2020 7:00 0,1 -0,12 0,02959409 | ||
| 52 | 30.01.2020 7:10 0,2 -0,13 0,16641980 | ||
| 53 | 30.01.2020 7:20 0,2 -0,13 0,16641980 | ||
| 54 | 30.01.2020 7:30 0,1 -0,13 0,16641980 | ||
| 55 | 30.01.2020 7:40 0,1 -0,13 0,16641980 | ||
| 56 | 30.01.2020 7:50 0,3 -0,13 0,16641980 | ||
| 57 | 30.01.2020 8:00 0,2 -0,13 0,16641980 | ||
| 58 | 30.01.2020 8:10 0,1 -0,13 0,39464354 | ||
| 59 | 30.01.2020 8:20 0,1 -0,13 0,16641980 | ||
| 60 | 30.01.2020 8:30 0 -0,13 0,16641980 | ||
| 61 | 30.01.2020 8:40 0 -0,13 0,16641980 | ||
| 62 | 30.01.2020 8:50 0,1 -0,13 0,16641980 | ||
| 63 | 30.01.2020 9:00 0 -0,13 0,16641980 | ||
| 64 | 30.01.2020 9:10 0 -0,13 0,09358473 | ||
| 65 | 30.01.2020 9:20 0 -0,12 0,09358473 | ||
| 66 | 30.01.2020 9:30 0 -0,11 0,03946435 | ||
| 67 | 30.01.2020 9:40 0 -0,11 0,03417472 | ||
| 68 | 30.01.2020 9:50 0 -0,09 0,00000000 | ||
| 69 | 30.01.2020 10:00 0 -0,08 0,00000000 | ||
| 70 | 30.01.2020 10:10 0 -0,07 0,00000000 | ||
| 71 | 30.01.2020 10:20 0 -0,05 0,00000000 | ||
| 72 | 30.01.2020 10:30 0 -0,04 0,00000000 | ||
| 73 | 30.01.2020 10:40 0 -0,03 0,00000000 | ||
| 74 | 30.01.2020 10:50 0 -0,02 0,00000000 | ||
| 75 | 30.01.2020 11:00 0 -0,02 0,00000000 | ||
| 76 | 30.01.2020 11:10 0 -0,01 0,00000000 | ||
| 77 | 30.01.2020 11:20 0 -0,01 0,00000000 | ||
| 78 | 30.01.2020 11:30 0 0,00 0,00000000 | ||
| 79 | 30.01.2020 11:40 0 0,01 0,00000000 | ||
| 80 | 30.01.2020 11:50 0 0,01 0,02562743 | ||
| 81 | 30.01.2020 12:00 0 0,01 0,00000000 | ||
| 82 | 30.01.2020 12:10 0 0,01 0,04557273 | ||
| 83 | 30.01.2020 12:20 0 0,01 0,02562743 | ||
| 84 | 30.01.2020 12:30 0 0,02 0,04557273 | ||
| 85 | 30.01.2020 12:40 0 0,02 0,02562743 | ||
| 86 | 30.01.2020 12:50 0 0,02 0,03417472 | ||
| 87 | 30.01.2020 13:00 0 0,03 0,02562743 | ||
| 88 | 30.01.2020 13:10 0 0,03 0,03417472 | ||
| 89 | 30.01.2020 13:20 0 0,03 0,03417472 | ||
| 90 | 30.01.2020 13:30 0 0,04 0,03417472 | ||
| 91 | 30.01.2020 13:40 2,3 0,03 0,03417472 | ||
| 92 | 30.01.2020 13:50 2 0,03 0,04557273 | ||
| 93 | 30.01.2020 14:00 4,1 0,03 0,04557273 | ||
| 94 | 30.01.2020 14:10 1,6 0,03 0,16641980 | ||
| 95 | 30.01.2020 14:20 0,5 0,03 0,34174723 | ||
| 96 | 30.01.2020 14:30 0,4 0,03 0,14411361 | ||
| 97 | 30.01.2020 14:40 3,5 0,03 0,22192437 | ||
| 98 | 30.01.2020 14:50 1,2 0,03 0,70178649 | ||
| 99 | 30.01.2020 15:00 0,2 0,03 0,34174723 | ||
| 100 | 30.01.2020 15:10 0,8 0,03 0,14411361 | ||
| 101 | 30.01.2020 15:20 0,9 0,04 0,70178649 | ||
| 102 | 30.01.2020 15:30 0,2 0,05 0,39464354 | ||
| 103 | 30.01.2020 15:40 0,4 0,05 0,39464354 | ||
| 104 | 30.01.2020 15:50 0,3 0,06 0,19217859 | ||
| 105 | 30.01.2020 16:00 0,3 0,06 0,70178649 | ||
| 106 | 30.01.2020 16:10 0,4 0,07 0,16641980 | ||
| 107 | 30.01.2020 16:20 0,3 0,09 0,14411361 | ||
| 108 | 30.01.2020 16:30 0,7 0,15 0,16641980 | ||
| 109 | 30.01.2020 16:40 0,5 0,25 0,16641980 | ||
| 110 | 30.01.2020 16:50 0,7 0,37 0,09358473 | ||
| 111 | 30.01.2020 17:00 0,5 0,50 0,08104104 | ||
| 112 | 30.01.2020 17:10 0,3 0,60 0,09358473 | ||
| 113 | 30.01.2020 17:20 0,3 0,68 0,09358473 | ||
| 114 | 30.01.2020 17:30 0,5 0,74 0,09358473 | ||
| 115 | 30.01.2020 17:40 0,5 0,76 0,09358473 | ||
| 116 | 30.01.2020 17:50 0,4 0,78 0,16641980 | ||
| 117 | 30.01.2020 18:00 0,5 0,79 0,16641980 | ||
| 118 | 30.01.2020 18:10 0,5 0,81 0,16641980 | ||
| 119 | 30.01.2020 18:20 0,3 0,82 0,16641980 | ||
| 120 | 30.01.2020 18:30 0,2 0,82 0,09358473 | ||
| 121 | 30.01.2020 18:40 0,2 0,82 0,09358473 | ||
| 122 | 30.01.2020 18:50 0,2 0,82 0,09358473 | ||
| 123 | 30.01.2020 19:00 0,4 0,83 0,16641980 | ||
| 124 | 30.01.2020 19:10 0,2 0,84 0,00000000 | ||
| 125 | 30.01.2020 19:20 0,1 0,84 0,00000000 | ||
| 126 | 30.01.2020 19:30 0,1 0,85 0,00000000 | ||
| 127 | 30.01.2020 19:40 0,1 0,86 0,00000000 | ||
| 128 | 30.01.2020 19:50 0,1 0,88 0,00000000 | ||
| 129 | 30.01.2020 20:00 0,1 0,89 0,00000000 | ||
| 130 | 30.01.2020 20:10 0 0,89 0,00000000 | ||
| 131 | 30.01.2020 20:20 0 0,91 0,00000000 | ||
| 132 | 30.01.2020 20:30 0 0,92 0,00000000 | ||
| 133 | 30.01.2020 20:40 0 0,93 0,00000000 | ||
| 134 | 30.01.2020 20:50 0 0,94 0,00000000 | ||
| 135 | 30.01.2020 21:00 0 0,93 0,00000000 | ||
| 136 | 30.01.2020 21:10 0 0,93 0,00000000 | ||
| 137 | 30.01.2020 21:20 0 0,93 0,00000000 | ||
| 138 | 30.01.2020 21:30 0 0,94 0,00000000 | ||
| 139 | 30.01.2020 21:40 0 0,94 0,00000000 | ||
| 140 | 30.01.2020 21:50 0 0,94 0,00000000 | ||
| 141 | 30.01.2020 22:00 0 0,94 0,00000000 | ||
| 142 | 30.01.2020 22:10 0 0,94 0,00000000 | ||
| 143 | 30.01.2020 22:20 0 0,94 0,00000000 | ||
| 144 | 30.01.2020 22:30 0 0,92 0,00000000 | ||
| 145 | 30.01.2020 22:40 0 0,92 0,00000000 | ||
| 146 | 30.01.2020 22:50 0 0,90 0,00000000 | ||
| 147 | 30.01.2020 23:00 0 0,89 0,00000000 | ||
| 148 | 30.01.2020 23:10 0 0,86 0,00000000 | ||
| 149 | 30.01.2020 23:20 0 0,84 0,00000000 | ||
| 150 | 30.01.2020 23:30 0 0,82 0,00000000 | ||
| 151 | 30.01.2020 23:40 0 0,80 0,00000000 | ||
| 152 | 30.01.2020 23:50 0 0,78 0,00000000 | ||
| 153 | 31.01.2020 0:00 0 0,76 0,00000000 | ||
| 154 | 31.01.2020 0:10 0 0,74 0,00000000 | ||
| 155 | 31.01.2020 0:20 0 0,72 0,00000000 | ||
| 156 | 31.01.2020 0:30 0 0,70 0,00000000 | ||
| 157 | 31.01.2020 0:40 0 0,69 0,00000000 | ||
| 158 | 31.01.2020 0:50 0 0,68 0,00000000 | ||
| 159 | 31.01.2020 1:00 0 0,66 0,00000000 | ||
| 160 | 31.01.2020 1:10 0 0,65 0,00000000 | ||
| 161 | 31.01.2020 1:20 0 0,64 0,00000000 | ||
| 162 | 31.01.2020 1:30 0 0,63 0,00000000 | ||
| 163 | 31.01.2020 1:40 0 0,62 0,00000000 | ||
| 164 | 31.01.2020 1:50 0 0,61 0,00000000 | ||
| 165 | 31.01.2020 2:00 0 0,60 0,00000000 | ||
| 166 | 31.01.2020 2:10 0,1 0,58 0,00000000 | ||
| 167 | 31.01.2020 2:20 0 0,57 0,00000000 | ||
| 168 | 31.01.2020 2:30 0,1 0,56 0,00000000 | ||
| 169 | 31.01.2020 2:40 0 0,55 0,00000000 | ||
| 170 | 31.01.2020 2:50 0 0,54 0,00000000 | ||
| 171 | 31.01.2020 3:00 0 0,53 0,00000000 | ||
| 172 | 31.01.2020 3:10 0 0,51 0,00000000 | ||
| 173 | 31.01.2020 3:20 0 0,51 0,00000000 | ||
| 174 | 31.01.2020 3:30 0 0,49 0,00000000 | ||
| 175 | 31.01.2020 3:40 0 0,47 0,00000000 | ||
| 176 | 31.01.2020 3:50 0 0,46 0,00000000 | ||
| 177 | 31.01.2020 4:00 0 0,45 0,00000000 | ||
| 178 | 31.01.2020 4:10 0 0,44 0,00000000 | ||
| 179 | 31.01.2020 4:20 0 0,43 0,00000000 | ||
| 180 | 31.01.2020 4:30 0 0,42 0,00000000 | ||
| 181 | 31.01.2020 4:40 0 0,41 0,00000000 | ||
| 182 | 31.01.2020 4:50 0 0,39 0,00000000 | ||
| 183 | 31.01.2020 5:00 0 0,39 0,00000000 | ||
| 184 | 31.01.2020 5:10 0 0,37 0,00000000 | ||
| 185 | 31.01.2020 5:20 0 0,36 0,00000000 | ||
| 186 | 31.01.2020 5:30 0 0,35 0,00000000 | ||
| 187 | 31.01.2020 5:40 0 0,35 0,00000000 | ||
| 188 | 31.01.2020 5:50 0 0,33 0,00000000 | ||
| 189 | 31.01.2020 6:00 0 0,32 0,00000000 | ||
| 190 | 31.01.2020 6:10 0 0,32 0,00000000 | ||
| 191 | 31.01.2020 6:20 0 0,31 0,00000000 | ||
| 192 | 31.01.2020 6:30 0 0,30 0,00000000 | ||
| 193 | 31.01.2020 6:40 0 0,29 0,00000000 | ||
| 194 | 31.01.2020 6:50 0 0,28 0,00000000 | ||
| 195 | 31.01.2020 7:00 0 0,27 0,00000000 | ||
| 196 | 31.01.2020 7:10 0 0,27 0,00000000 | ||
| 197 | 31.01.2020 7:20 0 0,26 0,00000000 | ||
| 198 | 31.01.2020 7:30 0 0,25 0,00000000 | ||
| 199 | 31.01.2020 7:40 0 0,25 0,00000000 | ||
| 200 | 31.01.2020 7:50 0 0,24 0,00000000 | ||
| 201 | 31.01.2020 8:00 0 0,23 0,00000000 | ||
| 202 | 31.01.2020 8:10 0 0,22 0,00000000 | ||
| 203 | 31.01.2020 8:20 0 0,22 0,00000000 | ||
| 204 | 31.01.2020 8:30 0 0,21 0,00000000 | ||
| 205 | 31.01.2020 8:40 0 0,20 0,00000000 | ||
| 206 | 31.01.2020 8:50 0 0,19 0,00000000 | ||
| 207 | 31.01.2020 9:00 0 0,19 0,00000000 | ||
| 208 | 31.01.2020 9:10 0 0,18 0,09358473 | ||
| 209 | 31.01.2020 9:20 0 0,18 0,09358473 | ||
| 210 | 31.01.2020 9:30 0 0,17 0,09358473 | ||
| 211 | 31.01.2020 9:40 0 0,17 0,04557273 | ||
| 212 | 31.01.2020 9:50 0 0,16 0,03417472 | ||
| 213 | 31.01.2020 10:00 0 0,15 0,09358473 | ||
| 214 | 31.01.2020 10:10 0 0,15 0,04557273 | ||
| 215 | 31.01.2020 10:20 0 0,14 0,03417472 | ||
| 216 | 31.01.2020 10:30 0 0,13 0,03417472 | ||
| 217 | 31.01.2020 10:40 0 0,13 0,03417472 | ||
| 218 | 31.01.2020 10:50 0 0,13 0,03417472 | ||
| 219 | 31.01.2020 11:00 0 0,12 0,00000000 | ||
| 220 | 31.01.2020 11:10 0 0,12 0,03417472 | ||
| 221 | 31.01.2020 11:20 0 0,11 0,03417472 | ||
| 222 | 31.01.2020 11:30 0 0,10 0,03417472 | ||
| 223 | 31.01.2020 11:40 0 0,10 0,03417472 | ||
| 224 | 31.01.2020 11:50 0 0,09 0,03417472 | ||
| 225 | 31.01.2020 12:00 0 0,09 0,03417472 | ||
| 226 | 31.01.2020 12:10 0 0,09 0,03417472 | ||
| 227 | 31.01.2020 12:20 0 0,08 0,03417472 | ||
| 228 | 31.01.2020 12:30 0 0,08 0,03417472 | ||
| 229 | 31.01.2020 12:40 0 0,08 0,03417472 | ||
| 230 | 31.01.2020 12:50 0 0,07 0,03417472 | ||
| 231 | 31.01.2020 13:00 0 0,07 0,00000000 | ||
| 232 | 31.01.2020 13:10 0 0,06 0,03417472 | ||
| 233 | 31.01.2020 13:20 0 0,06 0,03417472 | ||
| 234 | 31.01.2020 13:30 0 0,06 0,03417472 | ||
| 235 | 31.01.2020 13:40 0 0,05 0,03417472 | ||
| 236 | 31.01.2020 13:50 0 0,05 0,03417472 | ||
| 237 | 31.01.2020 14:00 0 0,04 0,03417472 | ||
| 238 | 31.01.2020 14:10 0 0,04 0,03417472 | ||
| 239 | 31.01.2020 14:20 0 0,04 0,03417472 | ||
| 240 | 31.01.2020 14:30 0 0,03 0,03417472 | ||
| 241 | 31.01.2020 14:40 0 0,03 0,03417472 | ||
| 242 | 31.01.2020 14:50 0 0,03 0,03417472 | ||
| 243 | 31.01.2020 15:00 0 0,02 0,03417472 | ||
| 244 | 31.01.2020 15:10 0 0,02 0,02562743 | ||
| 245 | 31.01.2020 15:20 0 0,02 0,02562743 | ||
| 246 | 31.01.2020 15:30 0 0,01 0,02562743 | ||
| 247 | 31.01.2020 15:40 0 0,01 0,02562743 | ||
| 248 | 31.01.2020 15:50 0 0,01 0,02562743 | ||
| 249 | 31.01.2020 16:00 0 0,01 0,02562743 | ||
| 250 | 31.01.2020 16:10 0 0,00 0,02562743 | ||
| 251 | 31.01.2020 16:20 0 -0,01 0,02562743 | ||
| 252 | 31.01.2020 16:30 0 -0,01 0,03417472 | ||
| 253 | 31.01.2020 16:40 0 -0,01 0,02562743 | ||
| 254 | 31.01.2020 16:50 0 -0,01 0,00000000 | ||
| 255 | 31.01.2020 17:00 0 -0,01 0,00000000 | ||
| 256 | 31.01.2020 17:10 0 -0,02 0,00000000 | ||
| 257 | 31.01.2020 17:20 0 -0,02 0,00000000 | ||
| 258 | 31.01.2020 17:30 0 -0,02 0,00000000 | ||
| 259 | 31.01.2020 17:40 0 -0,02 0,00000000 | ||
| 260 | 31.01.2020 17:50 0 -0,03 0,00000000 | ||
| 261 | 31.01.2020 18:00 0 -0,03 0,00000000 | ||
| 262 | 31.01.2020 18:10 0 -0,03 0,00000000 | ||
| 263 | 31.01.2020 18:20 0 -0,04 0,00000000 | ||
| 264 | 31.01.2020 18:30 0 -0,03 0,00000000 | ||
| 265 | 31.01.2020 18:40 0 -0,04 0,00000000 | ||
| 266 | 31.01.2020 18:50 0 -0,05 0,00000000 | ||
| 267 | 31.01.2020 19:00 0 -0,05 0,00000000 | ||
| 268 | 31.01.2020 19:10 0 -0,05 0,00000000 | ||
| 269 | 31.01.2020 19:20 0 -0,05 0,00000000 | ||
| 270 | 31.01.2020 19:30 0 -0,06 0,00000000 | ||
| 271 | 31.01.2020 19:40 0 -0,06 0,00000000 | ||
| 272 | 31.01.2020 19:50 0 -0,06 0,00000000 | ||
| 273 | 31.01.2020 20:00 0 -0,07 0,00000000 | ||
| 274 | 31.01.2020 20:10 0 -0,07 0,00000000 | ||
| 275 | 31.01.2020 20:20 0 -0,07 0,00000000 | ||
| 276 | 31.01.2020 20:30 0 -0,08 0,00000000 | ||
| 277 | 31.01.2020 20:40 0 -0,09 0,00000000 | ||
| 278 | 31.01.2020 20:50 0 -0,10 0,00000000 | ||
| 279 | 31.01.2020 21:00 0 -0,10 0,00000000 | ||
| 280 | 31.01.2020 21:10 0 -0,10 0,00000000 | ||
| 281 | 31.01.2020 21:20 0 -0,10 0,00000000 | ||
| 282 | 31.01.2020 21:30 0 -0,10 0,00000000 | ||
| 283 | 31.01.2020 21:40 0 -0,10 0,00000000 | ||
| 284 | 31.01.2020 21:50 0 -0,11 0,00000000 | ||
| 285 | 31.01.2020 22:00 0 -0,11 0,00000000 | ||
| 286 | 31.01.2020 22:10 0 -0,11 0,00000000 | ||
| 287 | 31.01.2020 22:20 0 -0,12 0,00000000 | ||
| 288 | 31.01.2020 22:30 0 -0,11 0,00000000 | ||
| 289 | 31.01.2020 22:40 0 -0,13 0,00000000 | ||
| 290 | 31.01.2020 22:50 0 -0,12 0,00000000 | ||
| 291 | 31.01.2020 23:00 0 -0,12 0,00000000 | ||
| 292 | 31.01.2020 23:10 0 -0,12 0,00000000 | ||
| 293 | 31.01.2020 23:20 0 -0,13 0,00000000 | ||
| 294 | 31.01.2020 23:30 0 -0,13 0,00000000 | ||
| 295 | 31.01.2020 23:40 0 -0,13 0,00000000 | ||
| 296 | 31.01.2020 23:50 0 -0,13 0,00000000 | ||
| 297 | 01.02.2020 0:00 0 -0,13 0,00000000 | ||
| 298 | 01.02.2020 0:10 0 -0,13 0,00000000 | ||
| 299 | 01.02.2020 0:20 0 -0,13 0,00000000 | ||
| 300 | 01.02.2020 0:30 0 -0,13 0,00000000 | ||
| 301 | 01.02.2020 0:40 0 -0,14 0,00000000 | ||
| 302 | 01.02.2020 0:50 0 -0,14 0,00000000 | ||
| 303 | 01.02.2020 1:00 0 -0,14 0,00000000 | ||
| 304 | 01.02.2020 1:10 0 -0,14 0,00000000 | ||
| 305 | 01.02.2020 1:20 0 -0,14 0,00000000 | ||
| 306 | 01.02.2020 1:30 0 -0,14 0,00000000 | ||
| 307 | 01.02.2020 1:40 0 -0,14 0,00000000 | ||
| 308 | 01.02.2020 1:50 0 -0,15 0,00000000 | ||
| 309 | 01.02.2020 2:00 0 -0,15 0,00000000 | ||
| 310 | 01.02.2020 2:10 0 -0,15 0,00000000 | ||
| 311 | 01.02.2020 2:20 0 -0,15 0,03417472 | ||
| 312 | 01.02.2020 2:30 0 -0,15 0,00000000 | ||
| 313 | 01.02.2020 2:40 0 -0,16 0,04557273 | ||
| 314 | 01.02.2020 2:50 0 -0,16 0,00000000 | ||
| 315 | 01.02.2020 3:00 0 -0,16 0,00000000 | ||
| 316 | 01.02.2020 3:10 0 -0,17 0,00000000 | ||
| 317 | 01.02.2020 3:20 0 -0,17 0,00000000 | ||
| 318 | 01.02.2020 3:30 0 -0,16 0,00000000 | ||
| 319 | 01.02.2020 3:40 0 -0,16 0,00000000 | ||
| 320 | 01.02.2020 3:50 0 -0,16 0,00000000 | ||
| 321 | 01.02.2020 4:00 0 -0,17 0,00000000 | ||
| 322 | 01.02.2020 4:10 0 -0,17 0,00000000 | ||
| 323 | 01.02.2020 4:20 0 -0,17 0,00000000 | ||
| 324 | 01.02.2020 4:30 0 -0,17 0,00000000 | ||
| 325 | 01.02.2020 4:40 0 -0,18 0,00000000 | ||
| 326 | 01.02.2020 4:50 0 -0,17 0,03946435 | ||
| 327 | 01.02.2020 5:00 0 -0,17 0,03946435 | ||
| 328 | 01.02.2020 5:10 0 -0,18 0,00000000 | ||
| 329 | 01.02.2020 5:20 0 -0,18 0,00000000 | ||
| 330 | 01.02.2020 5:30 0 -0,17 0,00000000 | ||
| 331 | 01.02.2020 5:40 0 -0,17 0,00000000 | ||
| 332 | 01.02.2020 5:50 0 -0,18 0,00000000 | ||
| 333 | 01.02.2020 6:00 0 -0,18 0,00000000 | ||
| 334 | 01.02.2020 6:10 0 -0,18 0,00000000 | ||
| 335 | 01.02.2020 6:20 0 -0,18 0,00000000 | ||
| 336 | 01.02.2020 6:30 0 -0,18 0,00000000 | ||
| 337 | 01.02.2020 6:40 0 -0,18 0,00000000 | ||
| 338 | 01.02.2020 6:50 0 -0,18 0,00000000 | ||
| 339 | 01.02.2020 7:00 0 -0,19 0,00000000 | ||
| 340 | 01.02.2020 7:10 0 -0,18 0,00000000 | ||
| 341 | 01.02.2020 7:20 0 -0,18 0,00000000 | ||
| 342 | 01.02.2020 7:30 0 -0,19 0,00000000 | ||
| 343 | 01.02.2020 7:40 0 -0,18 0,00000000 | ||
| 344 | 01.02.2020 7:50 0 -0,18 0,00000000 | ||
| 345 | 01.02.2020 8:00 0 -0,18 0,00000000 | ||
| 346 | 01.02.2020 8:10 0 -0,18 0,00000000 | ||
| 347 | 01.02.2020 8:20 0 -0,17 0,00000000 | ||
| 348 | 01.02.2020 8:30 0 -0,18 0,00000000 | ||
| 349 | 01.02.2020 8:40 0 -0,17 0,00000000 | ||
| 350 | 01.02.2020 8:50 0 -0,18 0,00000000 | ||
| 351 | 01.02.2020 9:00 0 -0,17 0,00000000 | ||
| 352 | 01.02.2020 9:10 0 -0,18 0,00000000 | ||
| 353 | 01.02.2020 9:20 0 -0,17 0,00000000 | ||
| 354 | 01.02.2020 9:30 0 -0,15 0,03417472 | ||
| 355 | 01.02.2020 9:40 0 -0,16 0,04557273 | ||
| 356 | 01.02.2020 9:50 0 -0,17 0,02959409 | ||
| 357 | 01.02.2020 10:00 0 -0,17 0,03417472 | ||
| 358 | 01.02.2020 10:10 0 -0,17 0,09358473 | ||
| 359 | 01.02.2020 10:20 0 -0,18 0,04557273 | ||
| 360 | 01.02.2020 10:30 0 -0,16 0,04557273 | ||
| 361 | 01.02.2020 10:40 0 -0,17 0,02959409 | ||
| 362 | 01.02.2020 10:50 0 -0,16 0,16641980 | ||
| 363 | 01.02.2020 11:00 0 -0,16 0,39464354 | ||
| 364 | 01.02.2020 11:10 0 -0,17 0,04557273 | ||
| 365 | 01.02.2020 11:20 0 -0,18 0,03417472 | ||
| 366 | 01.02.2020 11:30 0 -0,17 0,04557273 | ||
| 367 | 01.02.2020 11:40 0 -0,18 0,00000000 | ||
| 368 | 01.02.2020 11:50 0 -0,18 0,00000000 | ||
| 369 | 01.02.2020 12:00 0 -0,17 0,00000000 | ||
| 370 | 01.02.2020 12:10 0 -0,18 0,00000000 | ||
| 371 | 01.02.2020 12:20 0 -0,18 0,00000000 | ||
| 372 | 01.02.2020 12:30 0 -0,18 0,00000000 | ||
| 373 | 01.02.2020 12:40 0 -0,18 0,00000000 | ||
| 374 | 01.02.2020 12:50 0 -0,18 0,03417472 | ||
| 375 | 01.02.2020 13:00 0 -0,19 0,00000000 | ||
| 376 | 01.02.2020 13:10 0 -0,19 0,00000000 | ||
| 377 | 01.02.2020 13:20 0 -0,18 0,00000000 | ||
| 378 | 01.02.2020 13:30 0 -0,19 0,00000000 | ||
| 379 | 01.02.2020 13:40 0 -0,18 0,00000000 | ||
| 380 | 01.02.2020 13:50 0 -0,18 0,00000000 | ||
| 381 | 01.02.2020 14:00 0 -0,18 0,00000000 | ||
| 382 | 01.02.2020 14:10 0 -0,17 0,00000000 | ||
| 383 | 01.02.2020 14:20 0 -0,17 0,00000000 | ||
| 384 | 01.02.2020 14:30 0 -0,17 0,00000000 | ||
| 385 | 01.02.2020 14:40 0 -0,17 0,00000000 | ||
| 386 | 01.02.2020 14:50 0 -0,18 0,00000000 | ||
| 387 | 01.02.2020 15:00 0 -0,18 0,00000000 | ||
| 388 | 01.02.2020 15:10 0 -0,17 0,04557273 | ||
| 389 | 01.02.2020 15:20 0 -0,17 0,00000000 | ||
| 390 | 01.02.2020 15:30 0 -0,16 0,00000000 | ||
| 391 | 01.02.2020 15:40 0 -0,16 0,00000000 | ||
| 392 | 01.02.2020 15:50 0 -0,17 0,00000000 | ||
| 393 | 01.02.2020 16:00 0 -0,16 0,00000000 | ||
| 394 | 01.02.2020 16:10 0 -0,16 0,00000000 | ||
| 395 | 01.02.2020 16:20 0 -0,16 0,00000000 | ||
| 396 | 01.02.2020 16:30 0 -0,15 0,00000000 | ||
| 397 | 01.02.2020 16:40 0 -0,15 0,00000000 | ||
| 398 | 01.02.2020 16:50 0 -0,15 0,00000000 | ||
| 399 | 01.02.2020 17:00 0 -0,15 0,04557273 | ||
| 400 | 01.02.2020 17:10 0 -0,14 0,07017865 | ||
| 401 | 01.02.2020 17:20 0 -0,14 0,04557273 | ||
| 402 | 01.02.2020 17:30 0 -0,14 0,08104104 | ||
| 403 | 01.02.2020 17:40 0 -0,12 0,09358473 | ||
| 404 | 01.02.2020 17:50 0 -0,13 0,09358473 | ||
| 405 | 01.02.2020 18:00 0 -0,13 0,03417472 | ||
| 406 | 01.02.2020 18:10 0 -0,14 0,04557273 | ||
| 407 | 01.02.2020 18:20 0 -0,14 0,16641980 | ||
| 408 | 01.02.2020 18:30 0 -0,13 0,04557273 | ||
| 409 | 01.02.2020 18:40 0 -0,14 0,03417472 | ||
| 410 | 01.02.2020 18:50 0 -0,14 0,09358473 | ||
| 411 | 01.02.2020 19:00 0,1 -0,13 0,09358473 | ||
| 412 | 01.02.2020 19:10 0,1 -0,14 0,09358473 | ||
| 413 | 01.02.2020 19:20 0,2 -0,12 0,09358473 | ||
| 414 | 01.02.2020 19:30 0 -0,11 0,09358473 | ||
| 415 | 01.02.2020 19:40 0,1 -0,13 0,00000000 | ||
| 416 | 01.02.2020 19:50 0,2 -0,11 0,00000000 | ||
| 417 | 01.02.2020 20:00 0,1 -0,11 0,00000000 | ||
| 418 | 01.02.2020 20:10 0,3 -0,13 0,09358473 | ||
| 419 | 01.02.2020 20:20 0,4 -0,12 0,16641980 | ||
| 420 | 01.02.2020 20:30 0,4 -0,12 0,09358473 | ||
| 421 | 01.02.2020 20:40 0,4 -0,13 0,16641980 | ||
| 422 | 01.02.2020 20:50 0,3 -0,10 0,09358473 | ||
| 423 | 01.02.2020 21:00 0,8 -0,13 0,16641980 | ||
| 424 | 01.02.2020 21:10 0,8 -0,13 0,16641980 | ||
| 425 | 01.02.2020 21:20 0,6 -0,13 0,16641980 | ||
| 426 | 01.02.2020 21:30 0,7 -0,10 0,16641980 | ||
| 427 | 01.02.2020 21:40 0,5 -0,11 0,16641980 | ||
| 428 | 01.02.2020 21:50 0,2 -0,11 0,16641980 | ||
| 429 | 01.02.2020 22:00 0 -0,11 0,09358473 | ||
| 430 | 01.02.2020 22:10 0,1 -0,14 0,09358473 | ||
| 431 | 01.02.2020 22:20 0,1 -0,13 0,09358473 | ||
| 432 | 01.02.2020 22:30 0,1 -0,13 0,16641980 | ||
| 433 | 01.02.2020 22:40 0,3 -0,10 0,00000000 | ||
| 434 | 01.02.2020 22:50 0,2 -0,11 0,16641980 | ||
| 435 | 01.02.2020 23:00 0,5 -0,09 0,16641980 | ||
| 436 | 01.02.2020 23:10 0,6 -0,10 0,16641980 | ||
| 437 | 01.02.2020 23:20 0,2 -0,11 0,14411361 | ||
| 438 | 01.02.2020 23:30 0,1 -0,11 0,16641980 | ||
| 439 | 01.02.2020 23:40 0,1 -0,12 0,16641980 | ||
| 440 | 01.02.2020 23:50 0,1 -0,09 0,39464354 | ||
| 441 | 02.02.2020 0:00 0,2 -0,10 0,19217859 | ||
| 442 | 02.02.2020 0:10 0,4 -0,11 0,39464354 | ||
| 443 | 02.02.2020 0:20 0,7 -0,09 0,16641980 | ||
| 444 | 02.02.2020 0:30 0,5 -0,10 0,16641980 | ||
| 445 | 02.02.2020 0:40 0 -0,10 0,16641980 | ||
| 446 | 02.02.2020 0:50 0,6 -0,10 0,09358473 | ||
| 447 | 02.02.2020 1:00 0,2 -0,09 0,09358473 | ||
| 448 | 02.02.2020 1:10 0,3 -0,09 0,16641980 | ||
| 449 | 02.02.2020 1:20 0,2 -0,08 0,16641980 | ||
| 450 | 02.02.2020 1:30 0,1 -0,04 0,09358473 | ||
| 451 | 02.02.2020 1:40 0,2 0,03 0,16641980 | ||
| 452 | 02.02.2020 1:50 0,2 0,09 0,16641980 | ||
| 453 | 02.02.2020 2:00 0,2 0,14 0,09358473 | ||
| 454 | 02.02.2020 2:10 0,1 0,17 0,16641980 | ||
| 455 | 02.02.2020 2:20 0,2 0,21 0,16641980 | ||
| 456 | 02.02.2020 2:30 0 0,25 0,16641980 | ||
| 457 | 02.02.2020 2:40 0,1 0,32 0,08104104 | ||
| 458 | 02.02.2020 2:50 0,1 0,39 0,08104104 | ||
| 459 | 02.02.2020 3:00 0,2 0,48 0,16641980 | ||
| 460 | 02.02.2020 3:10 0 0,55 0,09358473 | ||
| 461 | 02.02.2020 3:20 0 0,62 0,16641980 | ||
| 462 | 02.02.2020 3:30 0 0,68 0,09358473 | ||
| 463 | 02.02.2020 3:40 0 0,71 0,16641980 | ||
| 464 | 02.02.2020 3:50 0 0,74 0,16641980 | ||
| 465 | 02.02.2020 4:00 0 0,77 0,03417472 | ||
| 466 | 02.02.2020 4:10 0 0,77 0,14411361 | ||
| 467 | 02.02.2020 4:20 0 0,79 0,02959409 | ||
| 468 | 02.02.2020 4:30 0 0,79 0,03417472 | ||
| 469 | 02.02.2020 4:40 0 0,78 0,08104104 | ||
| 470 | 02.02.2020 4:50 0 0,78 0,09358473 | ||
| 471 | 02.02.2020 5:00 0 0,77 0,04557273 | ||
| 472 | 02.02.2020 5:10 0 0,76 0,04557273 | ||
| 473 | 02.02.2020 5:20 0 0,76 0,19217859 | ||
| 474 | 02.02.2020 5:30 0 0,76 0,19217859 | ||
| 475 | 02.02.2020 5:40 0 0,75 0,02959409 | ||
| 476 | 02.02.2020 5:50 0 0,75 0,02959409 | ||
| 477 | 02.02.2020 6:00 0 0,73 0,04557273 | ||
| 478 | 02.02.2020 6:10 0 0,72 0,03417472 | ||
| 479 | 02.02.2020 6:20 0 0,70 0,03417472 | ||
| 480 | 02.02.2020 6:30 0 0,68 0,02959409 | ||
| 481 | 02.02.2020 6:40 0 0,66 0,08104104 | ||
| 482 | 02.02.2020 6:50 0 0,64 0,02959409 | ||
| 483 | 02.02.2020 7:00 0 0,61 0,04557273 | ||
| 484 | 02.02.2020 7:10 0 0,59 0,00000000 | ||
| 485 | 02.02.2020 7:20 0 0,57 0,08104104 | ||
| 486 | 02.02.2020 7:30 0 0,55 0,16641980 | ||
| 487 | 02.02.2020 7:40 0 0,54 0,16641980 | ||
| 488 | 02.02.2020 7:50 0 0,52 0,03946435 | ||
| 489 | 02.02.2020 8:00 0 0,51 0,09358473 | ||
| 490 | 02.02.2020 8:10 0 0,50 0,02959409 | ||
| 491 | 02.02.2020 8:20 0 0,49 0,07017865 | ||
| 492 | 02.02.2020 8:30 0 0,48 0,16641980 | ||
| 493 | 02.02.2020 8:40 0 0,47 0,09358473 | ||
| 494 | 02.02.2020 8:50 0 0,45 0,09358473 | ||
| 495 | 02.02.2020 9:00 0 0,44 0,00000000 | ||
| 496 | 02.02.2020 9:10 0 0,43 0,00000000 | ||
| 497 | 02.02.2020 9:20 0 0,42 0,04557273 | ||
| 498 | 02.02.2020 9:30 0 0,41 0,16641980 | ||
| 499 | 02.02.2020 9:40 0 0,41 0,39464354 | ||
| 500 | 02.02.2020 9:50 0 0,39 0,14411361 | ||
| 501 | 02.02.2020 10:00 0 0,39 0,07017865 | ||
| 502 | 02.02.2020 10:10 0 0,39 0,07017865 | ||
| 503 | 02.02.2020 10:20 0 0,38 0,04557273 | ||
| 504 | 02.02.2020 10:30 0 0,37 0,04557273 | ||
| 505 | 02.02.2020 10:40 0 0,37 0,00000000 | ||
| 506 | 02.02.2020 10:50 0 0,36 0,16641980 | ||
| 507 | 02.02.2020 11:00 0 0,36 0,05262656 | ||
| 508 | 02.02.2020 11:10 0 0,35 0,16641980 | ||
| 509 | 02.02.2020 11:20 0 0,35 0,16641980 | ||
| 510 | 02.02.2020 11:30 0 0,35 0,14411361 | ||
| 511 | 02.02.2020 11:40 0 0,34 0,16641980 | ||
| 512 | 02.02.2020 11:50 0 0,35 0,00000000 | ||
| 513 | 02.02.2020 12:00 0 0,36 0,04557273 | ||
| 514 | 02.02.2020 12:10 0 0,36 0,00000000 | ||
| 515 | 02.02.2020 12:20 0 0,37 0,00000000 | ||
| 516 | 02.02.2020 12:30 0 0,38 0,00000000 | ||
| 517 | 02.02.2020 12:40 0 0,39 0,00000000 | ||
| 518 | 02.02.2020 12:50 0 0,40 0,00000000 | ||
| 519 | 02.02.2020 13:00 0 0,40 0,03417472 | ||
| 520 | 02.02.2020 13:10 0 0,42 0,03417472 | ||
| 521 | 02.02.2020 13:20 0 0,42 0,02959409 | ||
| 522 | 02.02.2020 13:30 0 0,43 0,03417472 | ||
| 523 | 02.02.2020 13:40 0 0,44 0,03417472 | ||
| 524 | 02.02.2020 13:50 0 0,44 0,16641980 | ||
| 525 | 02.02.2020 14:00 0 0,43 0,39464354 | ||
| 526 | 02.02.2020 14:10 0 0,43 0,39464354 | ||
| 527 | 02.02.2020 14:20 0 0,43 0,39464354 | ||
| 528 | 02.02.2020 14:30 0 0,42 0,39464354 | ||
| 529 | 02.02.2020 14:40 0 0,42 0,19217859 | ||
| 530 | 02.02.2020 14:50 0 0,42 0,19217859 | ||
| 531 | 02.02.2020 15:00 0 0,42 0,16641980 | ||
| 532 | 02.02.2020 15:10 0 0,41 0,16641980 | ||
| 533 | 02.02.2020 15:20 0 0,39 0,16641980 | ||
| 534 | 02.02.2020 15:30 0 0,39 0,39464354 | ||
| 535 | 02.02.2020 15:40 0 0,39 0,16641980 | ||
| 536 | 02.02.2020 15:50 0 0,38 0,16641980 | ||
| 537 | 02.02.2020 16:00 0 0,37 0,16641980 | ||
| 538 | 02.02.2020 16:10 0 0,37 0,08104104 | ||
| 539 | 02.02.2020 16:20 0 0,37 0,09358473 | ||
| 540 | 02.02.2020 16:30 0 0,37 0,16641980 | ||
| 541 | 02.02.2020 16:40 0 0,36 0,04557273 | ||
| 542 | 02.02.2020 16:50 0 0,36 0,04557273 | ||
| 543 | 02.02.2020 17:00 0 0,37 0,00000000 | ||
| 544 | 02.02.2020 17:10 0 0,38 0,03417472 | ||
| 545 | 02.02.2020 17:20 0 0,38 0,00000000 | ||
| 546 | 02.02.2020 17:30 0 0,39 0,00000000 | ||
| 547 | 02.02.2020 17:40 0 0,40 0,00000000 | ||
| 548 | 02.02.2020 17:50 0 0,41 0,00000000 | ||
| 549 | 02.02.2020 18:00 0 0,43 0,00000000 | ||
| 550 | 02.02.2020 18:10 0 0,44 0,00000000 | ||
| 551 | 02.02.2020 18:20 0 0,45 0,03417472 | ||
| 552 | 02.02.2020 18:30 0 0,46 0,08104104 | ||
| 553 | 02.02.2020 18:40 0 0,49 0,16641980 | ||
| 554 | 02.02.2020 18:50 0 0,49 0,04557273 | ||
| 555 | 02.02.2020 19:00 0 0,49 0,04557273 | ||
| 556 | 02.02.2020 19:10 0 0,49 0,04557273 | ||
| 557 | 02.02.2020 19:20 0 0,49 0,03417472 | ||
| 558 | 02.02.2020 19:30 0 0,48 0,03417472 | ||
| 559 | 02.02.2020 19:40 0 0,47 0,09358473 | ||
| 560 | 02.02.2020 19:50 0 0,46 0,03417472 | ||
| 561 | 02.02.2020 20:00 0 0,45 0,03417472 | ||
| 562 | 02.02.2020 20:10 0 0,44 0,04557273 | ||
| 563 | 02.02.2020 20:20 0 0,43 0,03417472 | ||
| 564 | 02.02.2020 20:30 0 0,41 0,03417472 | ||
| 565 | 02.02.2020 20:40 0 0,41 0,04557273 | ||
| 566 | 02.02.2020 20:50 0 0,39 0,05262656 | ||
| 567 | 02.02.2020 21:00 0 0,38 0,02959409 | ||
| 568 | 02.02.2020 21:10 0 0,38 0,03417472 | ||
| 569 | 02.02.2020 21:20 0 0,36 0,04557273 | ||
| 570 | 02.02.2020 21:30 0 0,34 0,04557273 | ||
| 571 | 02.02.2020 21:40 0 0,35 0,04557273 | ||
| 572 | 02.02.2020 21:50 0 0,33 0,04557273 | ||
| 573 | 02.02.2020 22:00 0 0,32 0,03417472 | ||
| 574 | 02.02.2020 22:10 0 0,31 0,03946435 | ||
| 575 | 02.02.2020 22:20 0 0,31 0,03417472 | ||
| 576 | 02.02.2020 22:30 0 0,30 0,02959409 | ||
| 577 | 02.02.2020 22:40 0 0,29 0,00000000 | ||
| 578 | 02.02.2020 22:50 0 0,28 0,03417472 | ||
| 579 | 02.02.2020 23:00 0 0,28 0,04557273 | ||
| 580 | 02.02.2020 23:10 0 0,28 0,03417472 | ||
| 581 | 02.02.2020 23:20 0 0,27 0,04557273 | ||
| 582 | 02.02.2020 23:30 0 0,28 0,03417472 | ||
| 583 | 02.02.2020 23:40 0 0,26 0,03417472 | ||
| 584 | 02.02.2020 23:50 0 0,25 0,03417472 | ||
| 585 | 03.02.2020 0:00 0 0,25 0,03417472 | ||
| 586 | 03.02.2020 0:10 0 0,25 0,03417472 | ||
| 587 | 03.02.2020 0:20 0 0,26 0,03417472 | ||
| 588 | 03.02.2020 0:30 0 0,24 0,03417472 | ||
| 589 | 03.02.2020 0:40 0 0,24 0,03417472 | ||
| 590 | 03.02.2020 0:50 0 0,22 0,03417472 | ||
| 591 | 03.02.2020 1:00 0 0,22 0,03417472 | ||
| 592 | 03.02.2020 1:10 0 0,23 0,03417472 | ||
| 593 | 03.02.2020 1:20 0 0,20 0,03417472 | ||
| 594 | 03.02.2020 1:30 0 0,22 0,03417472 | ||
| 595 | 03.02.2020 1:40 0 0,22 0,03417472 | ||
| 596 | 03.02.2020 1:50 0 0,23 0,00000000 | ||
| 597 | 03.02.2020 2:00 0 0,20 0,00000000 | ||
| 598 | 03.02.2020 2:10 0 0,21 0,03417472 | ||
| 599 | 03.02.2020 2:20 0 0,19 0,03417472 | ||
| 600 | 03.02.2020 2:30 0 0,20 0,04557273 | ||
| 601 | 03.02.2020 2:40 0 0,18 0,09358473 | ||
| 602 | 03.02.2020 2:50 0 0,18 0,16641980 | ||
| 603 | 03.02.2020 3:00 0 0,18 0,08104104 | ||
| 604 | 03.02.2020 3:10 0 0,18 0,70178649 | ||
| 605 | 03.02.2020 3:20 0 0,18 0,09358473 | ||
| 606 | 03.02.2020 3:30 0 0,17 0,16641980 | ||
| 607 | 03.02.2020 3:40 0 0,17 0,16641980 | ||
| 608 | 03.02.2020 3:50 0 0,17 0,16641980 | ||
| 609 | 03.02.2020 4:00 0 0,17 0,09358473 | ||
| 610 | 03.02.2020 4:10 0 0,18 0,03417472 | ||
| 611 | 03.02.2020 4:20 0 0,18 0,03417472 | ||
| 612 | 03.02.2020 4:30 0 0,18 0,02959409 | ||
| 613 | 03.02.2020 4:40 0 0,18 0,09358473 | ||
| 614 | 03.02.2020 4:50 0 0,16 0,39464354 | ||
| 615 | 03.02.2020 5:00 0 0,17 0,09358473 | ||
| 616 | 03.02.2020 5:10 0 0,16 0,39464354 | ||
| 617 | 03.02.2020 5:20 0 0,17 0,70178649 | ||
| 618 | 03.02.2020 5:30 0 0,16 0,39464354 | ||
| 619 | 03.02.2020 5:40 0 0,16 0,16641980 | ||
| 620 | 03.02.2020 5:50 0 0,16 0,16641980 | ||
| 621 | 03.02.2020 6:00 0 0,17 0,39464354 | ||
| 622 | 03.02.2020 6:10 0 0,18 0,14411361 | ||
| 623 | 03.02.2020 6:20 0 0,18 0,16641980 | ||
| 624 | 03.02.2020 6:30 0 0,18 0,22192437 | ||
| 625 | 03.02.2020 6:40 0 0,19 0,22192437 | ||
| 626 | 03.02.2020 6:50 0 0,20 0,39464354 | ||
| 627 | 03.02.2020 7:00 0 0,22 0,19217859 | ||
| 628 | 03.02.2020 7:10 0 0,25 0,29594091 | ||
| 629 | 03.02.2020 7:20 0 0,30 0,08104104 | ||
| 630 | 03.02.2020 7:30 0 0,47 0,09358473 | ||
| 631 | 03.02.2020 7:40 0 0,87 0,04557273 | ||
| 632 | 03.02.2020 7:50 0 1,20 0,00000000 | ||
| 633 | 03.02.2020 8:00 0 1,46 0,00000000 | ||
| 634 | 03.02.2020 8:10 0 1,61 0,00000000 | ||
| 635 | 03.02.2020 8:20 0 1,71 0,00000000 | ||
| 636 | 03.02.2020 8:30 0 1,78 0,00000000 | ||
| 637 | 03.02.2020 8:40 0 1,69 0,00000000 | ||
| 638 | 03.02.2020 8:50 0 1,67 0,00000000 | ||
| 639 | 03.02.2020 9:00 0 1,56 0,00000000 | ||
| 640 | 03.02.2020 9:10 0 1,51 0,00000000 | ||
| 641 | 03.02.2020 9:20 0 1,39 0,00000000 | ||
| 642 | 03.02.2020 9:30 0 1,32 0,00000000 | ||
| 643 | 03.02.2020 9:40 0 1,23 0,00000000 | ||
| 644 | 03.02.2020 9:50 0 1,15 0,00000000 | ||
| 645 | 03.02.2020 10:00 0 1,09 0,00000000 | ||
| 646 | 03.02.2020 10:10 0 1,03 0,00000000 | ||
| 647 | 03.02.2020 10:20 0 0,97 0,00000000 | ||
| 648 | 03.02.2020 10:30 0 0,93 0,03417472 | ||
| 649 | 03.02.2020 10:40 0 0,88 0,04557273 | ||
| 650 | 03.02.2020 10:50 0 0,84 0,02562743 | ||
| 651 | 03.02.2020 11:00 0 0,79 0,00000000 | ||
| 652 | 03.02.2020 11:10 0 0,76 0,00000000 | ||
| 653 | 03.02.2020 11:20 0 0,72 0,00000000 | ||
| 654 | 03.02.2020 11:30 0 0,69 0,03417472 | ||
| 655 | 03.02.2020 11:40 0 0,66 0,14411361 | ||
| 656 | 03.02.2020 11:50 0 0,64 0,02562743 | ||
| 657 | 03.02.2020 12:00 0 0,61 0,09358473 | ||
| 658 | 03.02.2020 12:10 0 0,59 0,04557273 | ||
| 659 | 03.02.2020 12:20 0 0,57 0,03417472 | ||
| 660 | 03.02.2020 12:30 0 0,55 0,04557273 | ||
| 661 | 03.02.2020 12:40 0 0,52 0,03417472 | ||
| 662 | 03.02.2020 12:50 0 0,51 0,02562743 | ||
| 663 | 03.02.2020 13:00 0 0,49 0,02562743 | ||
| 664 | 03.02.2020 13:10 0 0,48 0,04557273 | ||
| 665 | 03.02.2020 13:20 0 0,46 0,03417472 | ||
| 666 | 03.02.2020 13:30 0 0,44 0,03417472 | ||
| 667 | 03.02.2020 13:40 0 0,42 0,03417472 | ||
| 668 | 03.02.2020 13:50 0 0,42 0,04557273 | ||
| 669 | 03.02.2020 14:00 0 0,41 0,03946435 | ||
| 670 | 03.02.2020 14:10 0 0,40 0,02562743 | ||
| 671 | 03.02.2020 14:20 0 0,38 0,02562743 | ||
| 672 | 03.02.2020 14:30 0 0,36 0,02562743 | ||
| 673 | 03.02.2020 14:40 0 0,36 0,02562743 | ||
| 674 | 03.02.2020 14:50 0 0,34 0,02562743 | ||
| 675 | 03.02.2020 15:00 0 0,33 0,03946435 | ||
| 676 | 03.02.2020 15:10 0 0,32 0,03417472 | ||
| 677 | 03.02.2020 15:20 0 0,31 0,03417472 | ||
| 678 | 03.02.2020 15:30 0 0,31 0,03417472 | ||
| 679 | 03.02.2020 15:40 0 0,31 0,03417472 | ||
| 680 | 03.02.2020 15:50 0 0,29 0,03417472 | ||
| 681 | 03.02.2020 16:00 0 0,29 0,03417472 | ||
| 682 | 03.02.2020 16:10 0 0,29 0,03417472 | ||
| 683 | 03.02.2020 16:20 0 0,27 0,03417472 | ||
| 684 | 03.02.2020 16:30 0 0,27 0,03417472 | ||
| 685 | 03.02.2020 16:40 0 0,27 0,04557273 | ||
| 686 | 03.02.2020 16:50 0 0,26 0,03417472 | ||
| 687 | 03.02.2020 17:00 0 0,24 0,03417472 | ||
| 688 | 03.02.2020 17:10 0 0,24 0,03417472 | ||
| 689 | 03.02.2020 17:20 0,2 0,24 0,07017865 | ||
| 690 | 03.02.2020 17:30 0,1 0,24 0,09358473 | ||
| 691 | 03.02.2020 17:40 0,1 0,23 0,09358473 | ||
| 692 | 03.02.2020 17:50 0,2 0,23 0,16641980 | ||
| 693 | 03.02.2020 18:00 0,2 0,22 0,16641980 | ||
| 694 | 03.02.2020 18:10 0,2 0,21 0,16641980 | ||
| 695 | 03.02.2020 18:20 0,3 0,21 0,29594091 | ||
| 696 | 03.02.2020 18:30 0,8 0,20 0,34174723 | ||
| 697 | 03.02.2020 18:40 0,6 0,20 0,19217859 | ||
| 698 | 03.02.2020 18:50 0,7 0,20 0,16641980 | ||
| 699 | 03.02.2020 19:00 0,6 0,21 0,22192437 | ||
| 700 | 03.02.2020 19:10 0,6 0,21 0,34174723 | ||
| 701 | 03.02.2020 19:20 0,3 0,20 0,19217859 | ||
| 702 | 03.02.2020 19:30 1,5 0,22 0,39464354 | ||
| 703 | 03.02.2020 19:40 1 0,21 0,52626562 | ||
| 704 | 03.02.2020 19:50 1,8 0,22 0,19217859 | ||
| 705 | 03.02.2020 20:00 1,6 0,22 0,39464354 | ||
| 706 | 03.02.2020 20:10 3,4 0,22 0,39464354 | ||
| 707 | 03.02.2020 20:20 3 0,24 0,14411361 | ||
| 708 | 03.02.2020 20:30 2,2 0,26 0,29594091 | ||
| 709 | 03.02.2020 20:40 1,4 0,28 0,22192437 | ||
| 710 | 03.02.2020 20:50 2,4 0,29 0,39464354 | ||
| 711 | 03.02.2020 21:00 2,1 0,32 0,39464354 | ||
| 712 | 03.02.2020 21:10 3,4 0,37 0,70178649 | ||
| 713 | 03.02.2020 21:20 3,9 0,44 0,39464354 | ||
| 714 | 03.02.2020 21:30 4,2 0,61 0,22192437 | ||
| 715 | 03.02.2020 21:40 3,6 0,90 0,70178649 | ||
| 716 | 03.02.2020 21:50 2,3 1,27 0,22192437 | ||
| 717 | 03.02.2020 22:00 2,2 1,65 0,22192437 | ||
| 718 | 03.02.2020 22:10 3,6 2,03 0,70178649 | ||
| 719 | 03.02.2020 22:20 3,7 2,38 0,70178649 | ||
| 720 | 03.02.2020 22:30 1,4 2,85 0,70178649 | ||
| 721 | 03.02.2020 22:40 1,9 2,97 0,34174723 | ||
| 722 | 03.02.2020 22:50 1,6 3,18 0,16641980 | ||
| 723 | 03.02.2020 23:00 1,3 3,34 0,39464354 | ||
| 724 | 03.02.2020 23:10 0,8 3,45 0,39464354 | ||
| 725 | 03.02.2020 23:20 0 3,55 0,34174723 | ||
| 726 | 03.02.2020 23:30 1,5 3,60 0,19217859 | ||
| 727 | 03.02.2020 23:40 0,5 3,71 0,16641980 | ||
| 728 | 03.02.2020 23:50 0,4 3,73 0,16641980 | ||
| 729 | 04.02.2020 0:00 0,1 3,76 0,16641980 | ||
| 730 | 04.02.2020 0:10 0,1 3,78 0,09358473 | ||
| 731 | 04.02.2020 0:20 0,1 3,76 0,09358473 | ||
| 732 | 04.02.2020 0:30 0 3,70 0,09358473 | ||
| 733 | 04.02.2020 0:40 0 3,63 0,09358473 | ||
| 734 | 04.02.2020 0:50 0 3,49 0,09358473 | ||
| 735 | 04.02.2020 1:00 0 3,32 0,03417472 | ||
| 736 | 04.02.2020 1:10 0 3,15 0,03417472 | ||
| 737 | 04.02.2020 1:20 0 2,95 0,09358473 | ||
| 738 | 04.02.2020 1:30 0 2,72 0,10806996 | ||
| 739 | 04.02.2020 1:40 0 2,51 0,09358473 | ||
| 740 | 04.02.2020 1:50 0,1 2,32 0,16641980 | ||
| 741 | 04.02.2020 2:00 0 2,15 0,16641980 | ||
| 742 | 04.02.2020 2:10 0 2,01 0,16641980 | ||
| 743 | 04.02.2020 2:20 0 1,87 0,16641980 | ||
| 744 | 04.02.2020 2:30 0 1,76 0,16641980 | ||
| 745 | 04.02.2020 2:40 0 1,66 0,16641980 | ||
| 746 | 04.02.2020 2:50 0 1,58 0,39464354 | ||
| 747 | 04.02.2020 3:00 0,1 1,51 0,39464354 | ||
| 748 | 04.02.2020 3:10 0,1 1,43 0,14411361 | ||
| 749 | 04.02.2020 3:20 0,1 1,37 0,19217859 | ||
| 750 | 04.02.2020 3:30 0 1,31 0,16641980 | ||
| 751 | 04.02.2020 3:40 0 1,27 0,08104104 | ||
| 752 | 04.02.2020 3:50 0 1,23 0,03417472 | ||
| 753 | 04.02.2020 4:00 0 1,17 0,03417472 | ||
| 754 | 04.02.2020 4:10 0 1,15 0,03417472 | ||
| 755 | 04.02.2020 4:20 0 1,10 0,03417472 | ||
| 756 | 04.02.2020 4:30 0 1,07 0,03417472 | ||
| 757 | 04.02.2020 4:40 0 1,03 0,02562743 | ||
| 758 | 04.02.2020 4:50 0 1,01 0,02562743 | ||
| 759 | 04.02.2020 5:00 0 0,98 0,00000000 | ||
| 760 | 04.02.2020 5:10 0 0,95 0,02562743 | ||
| 761 | 04.02.2020 5:20 0 0,93 0,00000000 | ||
| 762 | 04.02.2020 5:30 0 0,90 0,00000000 | ||
| 763 | 04.02.2020 5:40 0 0,87 0,00000000 | ||
| 764 | 04.02.2020 5:50 0 0,84 0,00000000 | ||
| 765 | 04.02.2020 6:00 0 0,82 0,00000000 | ||
| 766 | 04.02.2020 6:10 0 0,79 0,00000000 | ||
| 767 | 04.02.2020 6:20 0 0,78 0,00000000 | ||
| 768 | 04.02.2020 6:30 0 0,75 0,00000000 | ||
| 769 | 04.02.2020 6:40 0 0,73 0,00000000 | ||
| 770 | 04.02.2020 6:50 0 0,72 0,00000000 | ||
| 771 | 04.02.2020 7:00 0 0,70 0,00000000 | ||
| 772 | 04.02.2020 7:10 0 0,68 0,00000000 | ||
| 773 | 04.02.2020 7:20 0 0,66 0,00000000 | ||
| 774 | 04.02.2020 7:30 0 0,65 0,00000000 | ||
| 775 | 04.02.2020 7:40 0 0,63 0,00000000 | ||
| 776 | 04.02.2020 7:50 0 0,62 0,00000000 | ||
| 777 | 04.02.2020 8:00 0 0,60 0,00000000 | ||
| 778 | 04.02.2020 8:10 0 0,59 0,00000000 | ||
| 779 | 04.02.2020 8:20 0 0,57 0,00000000 | ||
| 780 | 04.02.2020 8:30 0 0,55 0,00000000 | ||
| 781 | 04.02.2020 8:40 0 0,54 0,00000000 | ||
| 782 | 04.02.2020 8:50 0 0,53 0,00000000 | ||
| 783 | 04.02.2020 9:00 0 0,52 0,00000000 | ||
| 784 | 04.02.2020 9:10 0 0,50 0,00000000 | ||
| 785 | 04.02.2020 9:20 0 0,49 0,00000000 | ||
| 786 | 04.02.2020 9:30 0 0,48 0,00000000 | ||
| 787 | 04.02.2020 9:40 0 0,46 0,00000000 | ||
| 788 | 04.02.2020 9:50 0 0,46 0,00000000 | ||
| 789 | 04.02.2020 10:00 0 0,44 0,00000000 | ||
| 790 | 04.02.2020 10:10 0 0,43 0,00000000 | ||
| 791 | 04.02.2020 10:20 0 0,42 0,00000000 | ||
| 792 | 04.02.2020 10:30 0 0,41 0,00000000 | ||
| 793 | 04.02.2020 10:40 0 0,40 0,00000000 | ||
| 794 | 04.02.2020 10:50 0 0,40 0,00000000 | ||
| 795 | 04.02.2020 11:00 0 0,38 0,00000000 | ||
| 796 | 04.02.2020 11:10 0 0,37 0,00000000 | ||
| 797 | 04.02.2020 11:20 0 0,36 0,00000000 | ||
| 798 | 04.02.2020 11:30 0 0,35 0,00000000 | ||
| 799 | 04.02.2020 11:40 0 0,34 0,00000000 | ||
| 800 | 04.02.2020 11:50 0 0,33 0,00000000 | ||
| 801 | 04.02.2020 12:00 0 0,32 0,00000000 | ||
| 802 | 04.02.2020 12:10 0 0,32 0,00000000 | ||
| 803 | 04.02.2020 12:20 0 0,31 0,00000000 | ||
| 804 | 04.02.2020 12:30 0 0,30 0,00000000 | ||
| 805 | 04.02.2020 12:40 0 0,30 0,00000000 | ||
| 806 | 04.02.2020 12:50 0 0,29 0,00000000 | ||
| 807 | 04.02.2020 13:00 0 0,28 0,00000000 | ||
| 808 | 04.02.2020 13:10 0 0,28 0,00000000 | ||
| 809 | 04.02.2020 13:20 0 0,26 0,00000000 | ||
| 810 | 04.02.2020 13:30 0 0,26 0,00000000 | ||
| 811 | 04.02.2020 13:40 0 0,26 0,00000000 | ||
| 812 | 04.02.2020 13:50 0 0,25 0,00000000 | ||
| 813 | 04.02.2020 14:00 0 0,25 0,00000000 | ||
| 814 | 04.02.2020 14:10 0 0,24 0,00000000 | ||
| 815 | 04.02.2020 14:20 0 0,24 0,00000000 | ||
| 816 | 04.02.2020 14:30 0 0,23 0,00000000 | ||
| 817 | 04.02.2020 14:40 0 0,22 0,00000000 | ||
| 818 | 04.02.2020 14:50 0 0,22 0,00000000 | ||
| 819 | 04.02.2020 15:00 0 0,21 0,00000000 | ||
| 820 | 04.02.2020 15:10 0 0,21 0,00000000 | ||
| 821 | 04.02.2020 15:20 0 0,20 0,00000000 | ||
| 822 | 04.02.2020 15:30 0 0,20 0,00000000 | ||
| 823 | 04.02.2020 15:40 0 0,19 0,00000000 |
9.09 KB
9.48 KB
21.4 KB
1.68 KB
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | import dateutil.parser | ||
| 13 | |||
| 14 | class DMRLPrecFile(): | ||
| 15 | |||
| 16 | def __init__(self, | ||
| 17 | _geo_lan = 44.417242, | ||
| 18 | _geo_lon = 38.72287, | ||
| 19 | _size = 256, | ||
| 20 | _lan_scale = 79497.3714882, | ||
| 21 | _lon_scale = 111162.6, | ||
| 22 | _pixel_size = 152.8740566, | ||
| 23 | _polygon = [], | ||
| 24 | _corr_geo_lan = 44.417242, | ||
| 25 | _corr_geo_lon = 38.72287, | ||
| 26 | _radar_a = 200, | ||
| 27 | _radar_n = 1.6, | ||
| 28 | _FILE_MODE=False, | ||
| 29 | _UID = "1a69563a-4d37-45df-98c4-4e72370efb1e"): | ||
| 30 | |||
| 31 | self.FILE_MODE = _FILE_MODE # РЕЖИМ ЧТЕНИЯ ДАННЫХ ИЗ ФАЙЛОВ | ||
| 32 | self.UID = _UID # Уникальный идентификатор измерителя | ||
| 33 | self.geo_lan = _geo_lan # ГеоКоординаты центра (широта), число - CALC FROM POLYGON | ||
| 34 | self.geo_lon = _geo_lon # ГеоКоординаты (долгота), число - CALC FROM POLYGON | ||
| 35 | self.size = _size # Размеры квадратной картинки, пикселей по широте и высоте - CONST=256 | ||
| 36 | self.lan_scale = _lan_scale # Длина дуги по широте (метров на градус) - CALC | ||
| 37 | self.lon_scale = _lon_scale # Длина дуги по долготе (метров на градус) - CALC | ||
| 38 | self.pixel_size = _pixel_size # Размер пикселя, метров на пиксель - CALC FROM SCALE | ||
| 39 | self.polygon = _polygon # Водосборный полигон, ([[id, name, lan, lon], [id, name, lan, lon], [id, name, lan, lon]...]) - INPUT | ||
| 40 | self.radar_a = _radar_a # Параметр А для расчёта осадков по ДБЗ - INPUT | ||
| 41 | self.radar_n = _radar_n # Параметр Н для расчета осадков по ДБЗ - INPUT | ||
| 42 | self.corr_geo_lan = _corr_geo_lan # Координаты АГК для корректировки (широта) | ||
| 43 | self.corr_geo_lon = _corr_geo_lon # Координаты АГК для корректировки (долгота) | ||
| 44 | |||
| 45 | self.xy_poligon = [] # Полигон в виде массива линейных координат (х, у) - CALC | ||
| 46 | self.grad_by_px_lon = 0 # Количество градусов в одном пикселе по долготе - CALC | ||
| 47 | self.grad_by_px_lan = 0 # Количество градусов в одном пикселе по широте - CALC | ||
| 48 | self.min_lon = 0 # Минимальная долгота картинки - CALC | ||
| 49 | self.min_lan = 0 # Минимальная широта картинки - CALC | ||
| 50 | self.max_lon = 0 # Максимальная долгота картинки - CALC | ||
| 51 | self.max_lan = 0 # Максимальная широта картинки - CALC | ||
| 52 | self.corr_x = -1 # Координаты корректировочного осадкомера (x) | ||
| 53 | self.corr_y = -1 # Координаты корректировочного осадкомера (y) | ||
| 54 | self.squere = 0.0 # Общая площадь водосбора | ||
| 55 | |||
| 56 | self.grad_by_px_lon = self.pixel_size / self.lon_scale # Количество градусов в одном пикселе по долготе | ||
| 57 | self.grad_by_px_lan = self.pixel_size / self.lan_scale # Количество градусов в одном пикселе по широте | ||
| 58 | self.min_lon = self.geo_lon - ((self.size / 2) * self.grad_by_px_lon) # Минимальная долгота картинки | ||
| 59 | self.min_lan = self.geo_lan - ((self.size / 2) * self.grad_by_px_lan) # Минимальная широта картинки | ||
| 60 | self.max_lon = self.geo_lon + ((self.size / 2) * self.grad_by_px_lon) # Максимальная долгота картинки | ||
| 61 | self.max_lan = self.geo_lan + ((self.size / 2) * self.grad_by_px_lan) # Максимальная широта картинки | ||
| 62 | |||
| 63 | |||
| 64 | # Параметры для корректировки | ||
| 65 | self.k_point_correction = 1 # Коэффициент корректировки точечный (интенсивность на осадкомере к интенсивносьти по радару в точке) | ||
| 66 | self.k_reserv_volume_store = dict(max_prec = -500.0, values = {}) # Резервное хранилище истории для поиска объёмов при отсутствии данных от ДМРЛ | ||
| 67 | |||
| 68 | # Определяем координаты Х,У для окорректировочного осадкомера | ||
| 69 | corr_point = self.GetXYPoint(self.corr_geo_lon, self.corr_geo_lan) | ||
| 70 | self.corr_x = corr_point["x"] | ||
| 71 | self.corr_y = corr_point["y"] | ||
| 72 | |||
| 73 | # Проверка параметров | ||
| 74 | self.CheckData() | ||
| 75 | |||
| 76 | # Генерируем полигон вида (х, у) | ||
| 77 | for point in self.polygon: | ||
| 78 | xy_point = self.GetXYPoint(point[3], point[2]) | ||
| 79 | if xy_point["x"] != -1 and xy_point["y"] != -1: | ||
| 80 | self.xy_poligon.append((xy_point["x"], xy_point["y"] )) | ||
| 81 | |||
| 82 | # Считаем площадь водосбора | ||
| 83 | img = np.zeros((self.size,self.size,4), np.uint8) | ||
| 84 | |||
| 85 | for yy in img: | ||
| 86 | for xx in yy: | ||
| 87 | xx[0] = 100 | ||
| 88 | xx[1] = 100 | ||
| 89 | xx[2] = 100 | ||
| 90 | xx[3] = 100 | ||
| 91 | |||
| 92 | img_mask = np.zeros(img.shape, dtype=np.uint8) | ||
| 93 | img_roi_corners = np.array([self.xy_poligon], dtype=np.int32) | ||
| 94 | img_ignore_mask_color = (255,)*4 | ||
| 95 | cv2.fillPoly(img_mask, img_roi_corners, img_ignore_mask_color) | ||
| 96 | img_masked_image = cv2.bitwise_and(img, img_mask) | ||
| 97 | |||
| 98 | ########################################### | ||
| 99 | # TODO Delete!!!! | ||
| 100 | #cv2.imwrite(os.path.abspath(os.curdir) + r'\result\all_squere.png', img_masked_image) | ||
| 101 | ########################################### | ||
| 102 | |||
| 103 | pcx_square_count = 0 | ||
| 104 | counter = 0 | ||
| 105 | |||
| 106 | for yy in img_masked_image: | ||
| 107 | for xx in yy: | ||
| 108 | counter = counter + 1 | ||
| 109 | if xx[0] == 100: | ||
| 110 | pcx_square_count = pcx_square_count + 1 | ||
| 111 | |||
| 112 | self.squere = self.pixel_size * self.pixel_size * pcx_square_count | ||
| 113 | |||
| 114 | # Проверка параметров | ||
| 115 | def CheckData(self): | ||
| 116 | if len(self.polygon) == 0: | ||
| 117 | raise BaseException("Полигон не указан") | ||
| 118 | |||
| 119 | if self.corr_geo_lan < 0 or self.corr_geo_lon < 0: | ||
| 120 | raise BaseException("Не удалось найти осадкомер с данными для корректировки") | ||
| 121 | |||
| 122 | if self.corr_geo_lon < self.min_lon or self.corr_geo_lon > self.max_lon or self.corr_geo_lan < self.min_lan or self.corr_geo_lan > self.max_lan: | ||
| 123 | raise BaseException("Координаты осадкомера для корректировки выходят за рамки исследуемой области:lon={}({}-{}), lan={}({}-{})".format( | ||
| 124 | self.corr_geo_lon, self.min_lon, self.max_lon, self.corr_geo_lan, self.min_lan, self.max_lan)) | ||
| 125 | |||
| 126 | for point in self.polygon: | ||
| 127 | if point[3] < self.min_lon or point[3] > self.max_lon or point[2] < self.min_lan or point[2] > self.max_lan: | ||
| 128 | raise BaseException("Координаты одной из точки полигона {} выходят за рамки исследуемой области:lon={}({}-{}), lan={}({}-{})".format( | ||
| 129 | point[1], point[3], self.min_lon, self.max_lon, point[2], self.min_lan, self.max_lan)) | ||
| 130 | |||
| 131 | return | ||
| 132 | |||
| 133 | # Получить осадки по значению dbZ | ||
| 134 | def GetPrecByDBZ(self, _dbz): | ||
| 135 | result = 0 | ||
| 136 | |||
| 137 | if _dbz == 0 or _dbz > 127: | ||
| 138 | return result | ||
| 139 | |||
| 140 | step1 = (_dbz - 32) / 10 | ||
| 141 | step2 = 10 ** step1 | ||
| 142 | step3 = step2 / self.radar_a | ||
| 143 | step4 = step3 ** (1.0/self.radar_n) | ||
| 144 | result = step4 | ||
| 145 | return result | ||
| 146 | |||
| 147 | # Получить точку (х, у) точке полигона в географических координатах | ||
| 148 | def GetXYPoint(self, _geo_lon, _geo_lan): | ||
| 149 | |||
| 150 | if _geo_lan < self.min_lan or _geo_lan > self.max_lan: | ||
| 151 | return dict(x = 0, y = -1) | ||
| 152 | |||
| 153 | if _geo_lon < self.min_lon or _geo_lon > self.max_lon: | ||
| 154 | return dict(x = -1, y = 0) | ||
| 155 | |||
| 156 | lon_delta = _geo_lon - self.min_lon | ||
| 157 | lan_delta = _geo_lan - self.max_lan | ||
| 158 | |||
| 159 | y_delta = lan_delta * self.lan_scale | ||
| 160 | x_delta = lon_delta * self.lon_scale | ||
| 161 | |||
| 162 | my = y_delta // self.pixel_size | ||
| 163 | mx = x_delta // self.pixel_size | ||
| 164 | |||
| 165 | result = dict(x = abs(mx), y = abs(my)) | ||
| 166 | return result | ||
| 167 | |||
| 168 | # Получить матрицу (из файла или онлайн) | ||
| 169 | def GetMatrix(self, _datetime): | ||
| 170 | result = None | ||
| 171 | |||
| 172 | ############################################################# | ||
| 173 | # Для файлового режима | ||
| 174 | if self.FILE_MODE == True: | ||
| 175 | # 1. Выделяем величину времени из даты | ||
| 176 | timestamp = int(_datetime.timestamp()) | ||
| 177 | file_path = r"\png\dj_286m_{}.png".format(timestamp) | ||
| 178 | |||
| 179 | # 2. Ищем файл и формируем матрицу | ||
| 180 | if not os.path.exists(os.path.abspath(os.curdir) + file_path): | ||
| 181 | return result | ||
| 182 | |||
| 183 | result = imread(os.path.abspath(os.curdir) + file_path) | ||
| 184 | ############################################################# | ||
| 185 | ############################################################# | ||
| 186 | |||
| 187 | ############################################################# | ||
| 188 | # Для web-режима | ||
| 189 | else: | ||
| 190 | |||
| 191 | # Определяем текущий тайм-слот | ||
| 192 | _datetime = datetime.datetime.now() | ||
| 193 | cur_min = (_datetime.minute // 10) * 10 | ||
| 194 | current_ts = datetime.datetime(_datetime.year, _datetime.month, _datetime.day, _datetime.hour, cur_min, 0, 0) | ||
| 195 | current_ts_ts = current_ts.timestamp() | ||
| 196 | last_ts = int(current_ts.timestamp()) + 600 | ||
| 197 | |||
| 198 | while datetime.datetime.now().timestamp() < last_ts: | ||
| 199 | |||
| 200 | time_result = None | ||
| 201 | time_url = 'https://tilecache.rainviewer.com/api/maps.json' | ||
| 202 | time_result = json.load(urllib.request.urlopen(time_url)) | ||
| 203 | |||
| 204 | if time_result is None or len(time_result) < 1 or current_ts_ts not in time_result: | ||
| 205 | print("{} No data...".format(datetime.datetime.now())) | ||
| 206 | time.sleep(30) | ||
| 207 | continue | ||
| 208 | |||
| 209 | img = None | ||
| 210 | |||
| 211 | try: | ||
| 212 | png_data_url = 'https://tilecache.rainviewer.com/v2/radar/{time}/256/10/{lan}/{lon}/0/0_0.png'.format( | ||
| 213 | time=current_ts_ts, | ||
| 214 | lan=self.geo_lan, | ||
| 215 | lon=self.geo_lon) | ||
| 216 | |||
| 217 | img = imread(png_data_url) | ||
| 218 | except: | ||
| 219 | continue | ||
| 220 | |||
| 221 | if img is not None: | ||
| 222 | result = img | ||
| 223 | |||
| 224 | if result is not None: | ||
| 225 | try: | ||
| 226 | mask = np.zeros(result.shape, dtype=np.uint8) | ||
| 227 | roi_corners = np.array([self.xy_poligon], dtype=np.int32) | ||
| 228 | l_shape = len(result.shape) | ||
| 229 | channel_count = result.shape[l_shape - 1] # i.e. 3 or 4 depending on your image | ||
| 230 | ignore_mask_color = (255,)*channel_count | ||
| 231 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 232 | masked_image = cv2.bitwise_and(result, mask) | ||
| 233 | result = masked_image | ||
| 234 | except(BaseException): | ||
| 235 | print("ERROR in file {}".format(os.path.abspath(os.curdir) + file_path)) | ||
| 236 | print(str(BaseException)) | ||
| 237 | return None | ||
| 238 | |||
| 239 | return result | ||
| 240 | |||
| 241 | # Получить данные по осадкам при отсутствии данных от ДМРЛ | ||
| 242 | def GetReservDataByPrec(self, _prec_value): | ||
| 243 | result = 0.0 | ||
| 244 | |||
| 245 | if _prec_value == 0.32: | ||
| 246 | print("kosyak....") | ||
| 247 | |||
| 248 | x1 = -1.0 | ||
| 249 | x2 = -1.0 | ||
| 250 | y1 = -1.0 | ||
| 251 | y2 = -1.0 | ||
| 252 | u_sort_keys = sorted(self.k_reserv_volume_store["values"].keys(), reverse=True) | ||
| 253 | sort_keys = sorted(self.k_reserv_volume_store["values"].keys(), reverse=False) | ||
| 254 | |||
| 255 | if _prec_value > self.k_reserv_volume_store["max_prec"]: | ||
| 256 | x1 = u_sort_keys[1] | ||
| 257 | x2 = u_sort_keys[0] | ||
| 258 | else: | ||
| 259 | if _prec_value in sort_keys: | ||
| 260 | result = self.k_reserv_volume_store["values"][_prec_value]["volume"] | ||
| 261 | return result | ||
| 262 | else: | ||
| 263 | counter = -1 | ||
| 264 | for key in sort_keys: | ||
| 265 | if key > _prec_value: | ||
| 266 | x1 = sort_keys[counter] | ||
| 267 | x2 = key | ||
| 268 | break | ||
| 269 | counter = counter + 1 | ||
| 270 | |||
| 271 | y1 = self.k_reserv_volume_store["values"][x1]["volume"] | ||
| 272 | y2 = self.k_reserv_volume_store["values"][x2]["volume"] | ||
| 273 | |||
| 274 | result = ((x2 * y1 - x1 * y2) / (x2 - x1)) - (y1 - y2) * _prec_value | ||
| 275 | result = (((y2-y1)/(x2-x1)) * (_prec_value - x1)) + y1 | ||
| 276 | |||
| 277 | if result < 0.0: | ||
| 278 | result = 0.0 | ||
| 279 | |||
| 280 | return result | ||
| 281 | |||
| 282 | # Добавить в историю резервных коэффициентов новое значение | ||
| 283 | def SetNewReservKoefficient(self, _prec, _volume): | ||
| 284 | |||
| 285 | if _prec == 0 and _volume == 0: | ||
| 286 | return | ||
| 287 | |||
| 288 | if _prec > self.k_reserv_volume_store["max_prec"]: | ||
| 289 | self.k_reserv_volume_store["max_prec"] = _prec | ||
| 290 | |||
| 291 | # 1. Если такого показателя осадков нет | ||
| 292 | if _prec not in self.k_reserv_volume_store["values"].keys(): | ||
| 293 | self.k_reserv_volume_store["values"][_prec] = dict(volume = _volume, counter = 1) | ||
| 294 | return | ||
| 295 | |||
| 296 | if _prec in self.k_reserv_volume_store["values"].keys(): | ||
| 297 | ex_volume = self.k_reserv_volume_store["values"][_prec]["volume"] | ||
| 298 | ex_counter = self.k_reserv_volume_store["values"][_prec]["counter"] | ||
| 299 | new_volume = ((ex_volume * ex_counter) + _volume) / (ex_counter + 1) | ||
| 300 | self.k_reserv_volume_store["values"][_prec]["volume"] = new_volume | ||
| 301 | self.k_reserv_volume_store["values"][_prec]["counter"] = ex_counter + 1 | ||
| 302 | return | ||
| 303 | |||
| 304 | return | ||
| 305 | |||
| 306 | # Конвертор для даты и времени в ДжСОН | ||
| 307 | def MyDateJsonConverter(self, o): | ||
| 308 | if isinstance(o, datetime.datetime): | ||
| 309 | return o.__str__() | ||
| 310 | |||
| 311 | # Получить результаты расчёта | ||
| 312 | def GetResult(self, _prec, _test_datetime=None): | ||
| 313 | """ | ||
| 314 | _prec это JSON вида: | ||
| 315 | {"time": "2020-03-20T10:00:00Z", | ||
| 316 | "period": 600, | ||
| 317 | "sum": 0.0, | ||
| 318 | "intensity": 0.0, | ||
| 319 | "type": 0} | ||
| 320 | """ | ||
| 321 | |||
| 322 | result = None | ||
| 323 | if _prec["sum"] == " ": | ||
| 324 | _prec = None | ||
| 325 | |||
| 326 | #self.k_point_correction = 1 # Коэффициент корректировки точечный (интенсивность на осадкомере к интенсивносьти по радару в точке) | ||
| 327 | #self.k_reserv_volume_prec = 1 # Резервный коэффициент (объем воды / текущие осадки на осадкомере) | ||
| 328 | temp_datetime = datetime.datetime.now() | ||
| 329 | temp_cur_min = (temp_datetime.minute // 10) * 10 | ||
| 330 | cur_datetime = datetime.datetime(temp_datetime.year, temp_datetime.month, temp_datetime.day, temp_datetime.hour, temp_cur_min, 0, 0) | ||
| 331 | |||
| 332 | if _prec is not None: | ||
| 333 | cur_datetime = dateutil.parser.parse(_prec["time"]) | ||
| 334 | |||
| 335 | if _test_datetime is not None: | ||
| 336 | cur_datetime = _test_datetime | ||
| 337 | |||
| 338 | matrix = self.GetMatrix(cur_datetime) | ||
| 339 | |||
| 340 | ##################################### | ||
| 341 | # TODO Delete!!!! | ||
| 342 | #temp_val = int(cur_datetime.timestamp()) | ||
| 343 | #temp_f_p = os.path.abspath(os.curdir) + '\\result\\{}.png'.format(int(cur_datetime.timestamp())) | ||
| 344 | #cv2.imwrite(temp_f_p, matrix) | ||
| 345 | ##################################### | ||
| 346 | |||
| 347 | # 1. Если ДМРЛ нет и нет осадков | ||
| 348 | if matrix is None and (_prec is None or _prec["sum"] == " "): | ||
| 349 | result = dict(time = cur_datetime.__str__(), | ||
| 350 | water_volume = -1.0, | ||
| 351 | prec_square = -1.0, | ||
| 352 | all_square = -1.0, | ||
| 353 | dmrl_prec = -1.0) | ||
| 354 | return json.dumps(result) | ||
| 355 | |||
| 356 | # 2. Если ДМРЛ нет, но есть осадки | ||
| 357 | if matrix is None and _prec is not None: | ||
| 358 | temp_volume = self.GetReservDataByPrec(float(_prec["sum"])) | ||
| 359 | result = dict(time = cur_datetime.__str__(), | ||
| 360 | water_volume = temp_volume, | ||
| 361 | prec_square = self.squere, | ||
| 362 | all_square = -1.0, | ||
| 363 | dmrl_prec = -1.0) | ||
| 364 | return json.dumps(result) | ||
| 365 | |||
| 366 | # 3-4. Если есть ДМРЛ и есть (или нет) осадков с АГК - ОБЫЧНЫЙ АЛГОРИТМ | ||
| 367 | # Определяем коэффициент корреляции, если оба значения есть и отличны от нуля | ||
| 368 | cur_prec_value = 0 | ||
| 369 | dmrl_prec = -1.0 | ||
| 370 | if _prec is not None: | ||
| 371 | cur_prec_value = float(_prec["sum"]) | ||
| 372 | |||
| 373 | test = matrix[0] | ||
| 374 | test = test[0] | ||
| 375 | test = test[0] | ||
| 376 | |||
| 377 | value = matrix[int(self.corr_y)][int(self.corr_x)][0] | ||
| 378 | dmrl_prec = self.GetPrecByDBZ(value) | ||
| 379 | dmrl_prec = dmrl_prec / 6 | ||
| 380 | |||
| 381 | if dmrl_prec > 0 and cur_prec_value > 0: | ||
| 382 | self.k_point_correction = cur_prec_value / dmrl_prec | ||
| 383 | |||
| 384 | sum_squere = 0.0 | ||
| 385 | vol_water = 0.0 | ||
| 386 | pixel_counter = 0.0 | ||
| 387 | for yy in matrix: | ||
| 388 | for xx in yy: | ||
| 389 | lm_value = xx[0] | ||
| 390 | m_prec = self.GetPrecByDBZ(lm_value) / 6.0 | ||
| 391 | |||
| 392 | vol_local = self.pixel_size * self.pixel_size * (1.0/1000.0) * m_prec * self.k_point_correction | ||
| 393 | vol_water = vol_water + vol_local | ||
| 394 | |||
| 395 | if vol_local > 0.0: | ||
| 396 | sum_squere = sum_squere + 1.0 | ||
| 397 | pixel_counter += 1.0 | ||
| 398 | |||
| 399 | sum_squere = sum_squere * self.pixel_size * self.pixel_size | ||
| 400 | |||
| 401 | result = dict(time = cur_datetime.__str__(), | ||
| 402 | water_volume = vol_water, | ||
| 403 | prec_square = sum_squere, | ||
| 404 | all_square = self.squere, | ||
| 405 | dmrl_prec = dmrl_prec) | ||
| 406 | |||
| 407 | self.SetNewReservKoefficient(cur_prec_value, vol_water) | ||
| 408 | |||
| 409 | return json.dumps(result) | ||
| 410 | ######################################################################## |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | import dateutil.parser | ||
| 13 | import dmrl_prec_file | ||
| 14 | |||
| 15 | class DMRLPrecFile_3SC(dmrl_prec_file.DMRLPrecFile): | ||
| 16 | |||
| 17 | # Получить результаты расчёта | ||
| 18 | def GetResult(self, _prec, _test_datetime=None): | ||
| 19 | """ | ||
| 20 | _prec это JSON вида: | ||
| 21 | {"time": "2020-03-20T10:00:00Z", | ||
| 22 | "period": 600, | ||
| 23 | "sum": 0.0, | ||
| 24 | "intensity": 0.0, | ||
| 25 | "type": 0} | ||
| 26 | """ | ||
| 27 | |||
| 28 | result = None | ||
| 29 | if _prec["sum"] == " ": | ||
| 30 | _prec = None | ||
| 31 | |||
| 32 | """ | ||
| 33 | result это JSON вида: | ||
| 34 | {"time": "2020-03-20T10:00:00Z", - время расчета | ||
| 35 | "water_volume": 0.0, - общее воличество выпавшей воды в м^3 | ||
| 36 | "prec_square": 0.0, - площадь выпадения осадков в м^2 | ||
| 37 | "all_square": 0.0} - общая площадь водосбора в м^2 | ||
| 38 | """ | ||
| 39 | |||
| 40 | #self.k_point_correction = 1 # Коэффициент корректировки точечный (интенсивность на осадкомере к интенсивносьти по радару в точке) | ||
| 41 | #self.k_reserv_volume_prec = 1 # Резервный коэффициент (объем воды / текущие осадки на осадкомере) | ||
| 42 | temp_datetime = datetime.datetime.now() | ||
| 43 | temp_cur_min = (temp_datetime.minute // 10) * 10 | ||
| 44 | cur_datetime = datetime.datetime(temp_datetime.year, temp_datetime.month, temp_datetime.day, temp_datetime.hour, temp_cur_min, 0, 0) | ||
| 45 | |||
| 46 | if _prec is not None: | ||
| 47 | #cur_datetime = dateutil.parser.parse(_prec["time"], ignoretz=False).replace(tzinfo=datetime.timezone.utc).astimezone(tz=None) | ||
| 48 | cur_datetime = dateutil.parser.parse(_prec["time"]) | ||
| 49 | |||
| 50 | if _test_datetime is not None: | ||
| 51 | cur_datetime = _test_datetime | ||
| 52 | |||
| 53 | matrix = self.GetMatrix(cur_datetime) | ||
| 54 | |||
| 55 | ##################################### | ||
| 56 | # TODO Delete!!!! | ||
| 57 | #temp_val = int(cur_datetime.timestamp()) | ||
| 58 | #temp_f_p = os.path.abspath(os.curdir) + '\\result\\{}.png'.format(int(cur_datetime.timestamp())) | ||
| 59 | #cv2.imwrite(temp_f_p, matrix) | ||
| 60 | ##################################### | ||
| 61 | |||
| 62 | # 1. Если ДМРЛ нет и нет осадков | ||
| 63 | if matrix is None and _prec is None: | ||
| 64 | result = dict(time = cur_datetime.__str__(), | ||
| 65 | water_volume = -1.0, | ||
| 66 | prec_square = -1.0, | ||
| 67 | all_square = -1.0, | ||
| 68 | dmrl_prec = -1.0) | ||
| 69 | return json.dumps(result) | ||
| 70 | |||
| 71 | |||
| 72 | # 2. Если ДМРЛ нет, но есть осадки | ||
| 73 | if matrix is None and _prec is not None: | ||
| 74 | temp_volume = self.GetReservDataByPrec(float(_prec["sum"])) | ||
| 75 | |||
| 76 | result = dict(time = cur_datetime.__str__(), | ||
| 77 | water_volume = temp_volume, | ||
| 78 | prec_square = self.squere, | ||
| 79 | all_square = -1.0) | ||
| 80 | return json.dumps(result) | ||
| 81 | |||
| 82 | # 3-4. Если есть ДМРЛ и есть (или нет) осадков с АГК - ОБЫЧНЫЙ АЛГОРИТМ | ||
| 83 | # Определяем коэффициент корреляции, если оба значения есть и отличны от нуля | ||
| 84 | cur_prec_value = 0 | ||
| 85 | if _prec is not None: | ||
| 86 | cur_prec_value = float(_prec["sum"]) | ||
| 87 | |||
| 88 | test = matrix[0] | ||
| 89 | test = test[0] | ||
| 90 | test = test[0] | ||
| 91 | |||
| 92 | value = matrix[int(self.corr_y)][int(self.corr_x)][0] | ||
| 93 | dmrl_prec = self.GetPrecByDBZ(value) | ||
| 94 | dmrl_prec = dmrl_prec / 6 | ||
| 95 | |||
| 96 | #################################################################### | ||
| 97 | # Работаем с коэффициентами корректировки | ||
| 98 | temp_k_point_correction = 1 | ||
| 99 | |||
| 100 | if dmrl_prec > 0 and cur_prec_value > 0: | ||
| 101 | temp_k_point_correction = cur_prec_value / dmrl_prec | ||
| 102 | |||
| 103 | if self.k_point_correction == 1 and self.k_count_point_correction == 0: | ||
| 104 | self.k_count_point_correction = 1 | ||
| 105 | self.k_math_waiting = temp_k_point_correction | ||
| 106 | self.k_dispersion = 0 | ||
| 107 | self.k_point_correction = temp_k_point_correction | ||
| 108 | else: | ||
| 109 | new_count = self.k_count_point_correction + 1 # Новое количество успешных попыток | ||
| 110 | |||
| 111 | mval1 = self.k_math_waiting * self.k_count_point_correction # сумма всех старых значений | ||
| 112 | mval2 = mval1 + self.k_point_correction # новая сумма значеий | ||
| 113 | mval3 = mval2 / new_count # Новое среднее (матожидание) | ||
| 114 | |||
| 115 | dval1 = (self.k_dispersion ** 2) * self.k_count_point_correction # сумма всех квадратов дельт старых | ||
| 116 | dval2 = (mval3 - temp_k_point_correction) ** 2 # новый квадрат дельты | ||
| 117 | dval4 = (dval1 + dval2) / new_count # общая сумма к общему кол-ву новая | ||
| 118 | dval5 = dval4 ** 0.5 # новое среднеквадратичное отклонение (типа дисперсия) | ||
| 119 | |||
| 120 | cval1 = temp_k_point_correction - mval3 # новое отклонение с учетом данной попытки | ||
| 121 | |||
| 122 | # Проверка на 3 сигмы | ||
| 123 | if abs(cval1) > abs(dval5) * 3.0: | ||
| 124 | temp_k_point_correction = mval3 + abs(dval5) * 3.0 * np.sign(cval1) | ||
| 125 | |||
| 126 | self.k_point_correction = temp_k_point_correction | ||
| 127 | |||
| 128 | #################################################################### | ||
| 129 | |||
| 130 | sum_squere = 0.0 | ||
| 131 | vol_water = 0.0 | ||
| 132 | pixel_counter = 0.0 | ||
| 133 | for yy in matrix: | ||
| 134 | for xx in yy: | ||
| 135 | lm_value = xx[0] | ||
| 136 | m_prec = self.GetPrecByDBZ(lm_value) / 6.0 | ||
| 137 | |||
| 138 | vol_local = self.pixel_size * self.pixel_size * (1.0/1000.0) * m_prec * self.k_point_correction | ||
| 139 | vol_water = vol_water + vol_local | ||
| 140 | |||
| 141 | if vol_local > 0.0: | ||
| 142 | sum_squere = sum_squere + 1.0 | ||
| 143 | pixel_counter += 1.0 | ||
| 144 | |||
| 145 | sum_squere = sum_squere * self.pixel_size * self.pixel_size | ||
| 146 | |||
| 147 | result = dict(time = cur_datetime.__str__(), | ||
| 148 | water_volume = vol_water, | ||
| 149 | prec_square = sum_squere, | ||
| 150 | all_square = self.squere) | ||
| 151 | |||
| 152 | self.SetNewReservKoefficient(cur_prec_value, vol_water) | ||
| 153 | |||
| 154 | return json.dumps(result) | ||
| 155 | ######################################################################## |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | import dateutil.parser | ||
| 13 | import dmrl_prec_file | ||
| 14 | |||
| 15 | class DMRLPrecFile_WOC(dmrl_prec_file.DMRLPrecFile): | ||
| 16 | |||
| 17 | # Получить результаты расчёта | ||
| 18 | def GetResult(self, _prec, _test_datetime=None): | ||
| 19 | """ | ||
| 20 | _prec это JSON вида: | ||
| 21 | {"time": "2020-03-20T10:00:00Z", | ||
| 22 | "period": 600, | ||
| 23 | "sum": 0.0, | ||
| 24 | "intensity": 0.0, | ||
| 25 | "type": 0} | ||
| 26 | """ | ||
| 27 | |||
| 28 | result = None | ||
| 29 | if _prec["sum"] == " ": | ||
| 30 | _prec = None | ||
| 31 | |||
| 32 | temp_datetime = datetime.datetime.now() | ||
| 33 | temp_cur_min = (temp_datetime.minute // 10) * 10 | ||
| 34 | cur_datetime = datetime.datetime(temp_datetime.year, temp_datetime.month, temp_datetime.day, temp_datetime.hour, temp_cur_min, 0, 0) | ||
| 35 | |||
| 36 | if _prec is not None: | ||
| 37 | cur_datetime = dateutil.parser.parse(_prec["time"]) | ||
| 38 | |||
| 39 | if _test_datetime is not None: | ||
| 40 | cur_datetime = _test_datetime | ||
| 41 | |||
| 42 | matrix = self.GetMatrix(cur_datetime) | ||
| 43 | |||
| 44 | # 1. Если ДМРЛ нет и нет осадков | ||
| 45 | if matrix is None: | ||
| 46 | result = dict(time = cur_datetime.__str__(), | ||
| 47 | water_volume = 0.0, | ||
| 48 | prec_square = 0.0, | ||
| 49 | all_square = -1.0, | ||
| 50 | dmrl_prec = -1.0) | ||
| 51 | return json.dumps(result) | ||
| 52 | |||
| 53 | # 3-4. Если есть ДМРЛ и есть (или нет) осадков с АГК - ОБЫЧНЫЙ АЛГОРИТМ | ||
| 54 | # Определяем коэффициент корреляции, если оба значения есть и отличны от нуля | ||
| 55 | cur_prec_value = 0 | ||
| 56 | dmrl_prec = -1.0 | ||
| 57 | |||
| 58 | sum_squere = 0.0 | ||
| 59 | vol_water = 0.0 | ||
| 60 | vol_water_wc = 0.0 | ||
| 61 | pixel_counter = 0.0 | ||
| 62 | for yy in matrix: | ||
| 63 | for xx in yy: | ||
| 64 | lm_value = xx[0] | ||
| 65 | m_prec = self.GetPrecByDBZ(lm_value) / 6.0 | ||
| 66 | |||
| 67 | vol_local_wc = self.pixel_size * self.pixel_size * (1.0/1000.0) * m_prec | ||
| 68 | |||
| 69 | vol_water_wc = vol_water_wc + vol_local_wc | ||
| 70 | |||
| 71 | if vol_water_wc > 0.0: | ||
| 72 | sum_squere = sum_squere + 1.0 | ||
| 73 | pixel_counter += 1.0 | ||
| 74 | |||
| 75 | sum_squere = sum_squere * self.pixel_size * self.pixel_size | ||
| 76 | |||
| 77 | if self.squere != 0.0: | ||
| 78 | dmrl_prec = vol_water_wc / self.squere | ||
| 79 | |||
| 80 | result = dict( | ||
| 81 | time = cur_datetime.__str__(), # Дата | ||
| 82 | water_volume = vol_water_wc, # объём воды (метры в кубе) | ||
| 83 | prec_square = sum_squere, # площадь выпадения осадков | ||
| 84 | all_square = self.squere, # общая площадь водосбора | ||
| 85 | dmrl_prec = dmrl_prec) # осадки (в мм) ОБЪЕМ ПРИВЕДЕННЫЙ К ОБЩЕЙ ПЛОЩАДИ ВОДОСБОРА | ||
| 86 | |||
| 87 | return json.dumps(result) | ||
| 88 | ######################################################################## |
| 1 | import math | ||
| 2 | |||
| 3 | # Общие константы | ||
| 4 | DELTA_CONST = 1e-6 | ||
| 5 | MIN_PART_DELTA_VAL = 1e-4 | ||
| 6 | MIN_DUML_INGRL_VAL = 1e-4 | ||
| 7 | |||
| 8 | # Единичный интеграл дюамеля | ||
| 9 | class DuhamelPart(): | ||
| 10 | |||
| 11 | def __init__(self, _beg_time, _amp, _t_per): | ||
| 12 | self.beg_time = _beg_time | ||
| 13 | self.amp = _amp | ||
| 14 | self.t_per = _t_per | ||
| 15 | self.is_const = False | ||
| 16 | |||
| 17 | def part_step(self, _calc_time): | ||
| 18 | if self.is_const: | ||
| 19 | return self.amp | ||
| 20 | exp_val = math.exp( (self.beg_time - _calc_time)/self.t_per ) | ||
| 21 | self.is_const = exp_val < DELTA_CONST | ||
| 22 | return self.amp * (1. - exp_val) | ||
| 23 | |||
| 24 | def const_part(self): | ||
| 25 | return self.is_const | ||
| 26 | |||
| 27 | |||
| 28 | # совокупность интегралов дюамеля | ||
| 29 | class DuhamelIntegral(): | ||
| 30 | |||
| 31 | def __init__(self, _up_per = 1.0, _down_per = 20.0): | ||
| 32 | # параметры интеграла | ||
| 33 | # вроде как вначале одинаковые для всех | ||
| 34 | self.curr_time = -1.0 | ||
| 35 | self.curr_src_val = 0.0 | ||
| 36 | |||
| 37 | # непосредственно влияющие на интеграл | ||
| 38 | self.up_per = _up_per | ||
| 39 | self.down_per = _down_per | ||
| 40 | |||
| 41 | self.parts_set = [] | ||
| 42 | self.duml_val = 0.0 | ||
| 43 | |||
| 44 | def add_part(self, delta): | ||
| 45 | if abs(delta) < MIN_PART_DELTA_VAL: | ||
| 46 | return | ||
| 47 | if delta > 0: | ||
| 48 | self.parts_set.append(DuhamelPart(self.curr_time, delta, self.up_per)) | ||
| 49 | else: | ||
| 50 | self.parts_set.append(DuhamelPart(self.curr_time, delta, self.down_per)) | ||
| 51 | |||
| 52 | def calc_step(self, calc_time): | ||
| 53 | self.duml_val = 0. | ||
| 54 | for part in self.parts_set: | ||
| 55 | self.duml_val += part.part_step(calc_time) | ||
| 56 | |||
| 57 | return self.duml_val | ||
| 58 | |||
| 59 | def duml_step(self, time, value): | ||
| 60 | self.add_part(value - self.curr_src_val) | ||
| 61 | self.curr_time = time | ||
| 62 | self.curr_src_val = value | ||
| 63 | return self.calc_step(self.curr_time) | ||
| 64 | |||
| 65 | def clear_parts_set(self): | ||
| 66 | if abs(self.duml_val) >= MIN_DUML_INGRL_VAL: | ||
| 67 | return | ||
| 68 | for part in self.parts_set: | ||
| 69 | if not part.const_part(): | ||
| 70 | return | ||
| 71 | self.parts_set = [] | ||
| 72 | |||
| 73 | # Полная модель интегралов дюамеля с учетом корректирующих коэффициентов | ||
| 74 | class DumlRiverModel: | ||
| 75 | |||
| 76 | def __init__(self, _k_n = 1.0, _k_korr = 25.0, _res_add_val = 20.0, _dmi_up_per = 1.0, _dmi_down_per = 20.0): | ||
| 77 | |||
| 78 | self.duml_intgrl = DuhamelIntegral(_down_per=_dmi_down_per, _up_per=_dmi_up_per) | ||
| 79 | |||
| 80 | self.k_n = _k_n # константный коэффициент коррекции результата | ||
| 81 | self.save_k_n = self.k_n | ||
| 82 | |||
| 83 | self.k_korr = _k_korr # настраиваемый коэффициент коррекции результата | ||
| 84 | self.save_k_korr = self.k_korr | ||
| 85 | |||
| 86 | self.res_add_val = _res_add_val # аддитивная величина коррекции результата | ||
| 87 | self.save_add_val = self.res_add_val | ||
| 88 | |||
| 89 | def model_step(self, time, value): | ||
| 90 | return self.k_n * self.k_korr * self.duml_intgrl.duml_step(time, value) + self.res_add_val | ||
| 91 | |||
| 92 | # Расчёт стока с водосборов | ||
| 93 | class CatchmentArea(): | ||
| 94 | def __init__(self, _capacity = 22.2, _in_filter = 1.0, _out_filter = 0.009): | ||
| 95 | # параметры водосбора | ||
| 96 | self.capacity = _capacity # вместимость водосбора, мм | ||
| 97 | self.in_filter = _in_filter # инфильтрация в почву за ед. периода, мм (за 10 мин) | ||
| 98 | self.out_filter = _out_filter # фильтрация из почвы за ед. периода, мм (за 10 мин) | ||
| 99 | self.level_delta = self.capacity | ||
| 100 | |||
| 101 | def calc_surface_flow(self, _rainfall): | ||
| 102 | мах_in = min(_rainfall, self.in_filter) | ||
| 103 | if мах_in <= self.level_delta: | ||
| 104 | self.level_delta -= мах_in | ||
| 105 | self.level_delta += self.out_filter | ||
| 106 | if self.level_delta > self.capacity: | ||
| 107 | self.level_delta = self.capacity | ||
| 108 | else: | ||
| 109 | self.level_delta += self.out_filter | ||
| 110 | if self.level_delta > self.capacity: | ||
| 111 | self.level_delta = self.capacity | ||
| 112 | мах_in = min(мах_in, self.level_delta) | ||
| 113 | self.level_delta -= мах_in | ||
| 114 | |||
| 115 | return _rainfall - мах_in | ||
| 116 | |||
| 117 | # реализация метода ньютона-рафсона | ||
| 118 | def newton_raphson(study_func, target_val, start_x, max_iter_count=10, max_err=1e-3, delta_x=1e-6): | ||
| 119 | |||
| 120 | # начальное значение аргумента | ||
| 121 | finded_x = start_x | ||
| 122 | |||
| 123 | # Цикл нахождения решения | ||
| 124 | iter_count = 0 | ||
| 125 | err_y = 1e20 | ||
| 126 | |||
| 127 | # цикл поиска решения | ||
| 128 | while (iter_count <= max_iter_count) and (abs(err_y) > max_err): | ||
| 129 | |||
| 130 | # Вычисляем производную dy/dx в точке x | ||
| 131 | # dfdx в принципе нам может быть известен аналитически, и в таком случае | ||
| 132 | # предпочтительно использовать аналитическое выражение. | ||
| 133 | dfdx = (study_func(finded_x + 0.5 * delta_x) - study_func(finded_x - 0.5 * delta_x)) / delta_x | ||
| 134 | |||
| 135 | # Находим приращение по y | ||
| 136 | err_y = study_func(finded_x) - target_val | ||
| 137 | # и по x | ||
| 138 | err_x = err_y / dfdx | ||
| 139 | # Получаем новое решение | ||
| 140 | finded_x = finded_x - err_x | ||
| 141 | |||
| 142 | # меняем к - во итераций | ||
| 143 | iter_count += 1 | ||
| 144 | |||
| 145 | return finded_x | ||
| 146 | |||
| 147 | # для расчёта уровня воды по расходу в створе | ||
| 148 | class RiverCrossSection(): | ||
| 149 | |||
| 150 | def __init__(self, _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): | ||
| 151 | # параметры трапеции | ||
| 152 | self._zero_wlevel = _zero_bsv | ||
| 153 | self._trap_a = _left_slope # ширина левого склона трапеции русла | ||
| 154 | self._trap_b = _bottom # ширина дна трапеции русла | ||
| 155 | self._trap_c = _right_slope # ширина правого склона трапеции русла | ||
| 156 | self._trap_d = _max_h # высота трапеции русла | ||
| 157 | if self._trap_d >= 0: | ||
| 158 | self._trap_leftCtg = self._trap_a / self._trap_d # котангенс левого угла трапеции русла | ||
| 159 | self._trap_rightCtg = self._trap_c / self._trap_d # котангенс правого угла трапеции русла | ||
| 160 | else: | ||
| 161 | self._trap_leftCtg = 0 # котангенс левого угла трапеции русла | ||
| 162 | self._trap_rightCtg = 0 # котангенс правого угла трапеции русла | ||
| 163 | |||
| 164 | self._i_rb_part = _i_bias # уклон русла | ||
| 165 | self._n_rb_part = _n_roughness # шероховатость русла | ||
| 166 | |||
| 167 | # площадь сечения (м^2) | ||
| 168 | def f_trap_area(self, h): | ||
| 169 | return self._trap_b * h + (self._trap_leftCtg + self._trap_rightCtg) * h * h / 2 | ||
| 170 | |||
| 171 | # смоченный периметр (м) | ||
| 172 | def f_trap_perimetr(self, h): | ||
| 173 | return self._trap_b + \ | ||
| 174 | math.sqrt(self._trap_leftCtg ** 2 + 1) * h + \ | ||
| 175 | math.sqrt(self._trap_rightCtg ** 2 + 1) * h | ||
| 176 | |||
| 177 | # гидрологический радиус | ||
| 178 | def f_hydro_r(self, h): | ||
| 179 | return self.f_trap_area(h) / self.f_trap_perimetr(h) | ||
| 180 | |||
| 181 | # скорость потока (м/с) | ||
| 182 | def f_flow_speed(self, h): | ||
| 183 | return self.f_hydro_r(h)**(2./3) * math.sqrt(self._i_rb_part) / self._n_rb_part | ||
| 184 | |||
| 185 | # расход воды (м^3/с) | ||
| 186 | def f_flow_rate(self, h): | ||
| 187 | if h <= 0.: | ||
| 188 | return 0. | ||
| 189 | return self.f_trap_area(h) * self.f_flow_speed(h) | ||
| 190 | |||
| 191 | # расход воды (м^3/с) | ||
| 192 | def f_flow_rate_by_bs_h(self, bs_h): | ||
| 193 | return self.f_flow_rate(bs_h - self._zero_wlevel) | ||
| 194 | |||
| 195 | # уровень воды (м), определяемый по расходу воды (м^3/с) | ||
| 196 | def high_by_flow_rate(self, flow_rate): | ||
| 197 | if flow_rate <= 0.: | ||
| 198 | return 0. | ||
| 199 | return newton_raphson(self.f_flow_rate, flow_rate, 1.) | ||
| 200 | |||
| 201 | # уровень воды (м), определяемый по расходу воды (м^3/с) по балтийской системе высот | ||
| 202 | def bs_water_level(self, flow_rate): | ||
| 203 | return self.high_by_flow_rate(flow_rate) + self._zero_wlevel |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | |||
| 13 | data_store = dict(max_prec = -500.0, values = {}) | ||
| 14 | |||
| 15 | prec_store = [] | ||
| 16 | prec_store.append([0.0, 0.0]) | ||
| 17 | prec_store.append([1.0, 2.0]) | ||
| 18 | prec_store.append([2.0, 4.0]) | ||
| 19 | prec_store.append([6.0, 12.0]) | ||
| 20 | prec_store.append([3.0, 6.0]) | ||
| 21 | prec_store.append([4.0, 8.0]) | ||
| 22 | prec_store.append([5.0, 10.0]) | ||
| 23 | |||
| 24 | |||
| 25 | for p in prec_store: | ||
| 26 | if p[0] > data_store["max_prec"]: | ||
| 27 | data_store["max_prec"] = p[0] | ||
| 28 | |||
| 29 | key = p[0] | ||
| 30 | sd = data_store["values"] | ||
| 31 | sd[key] = p[1] | ||
| 32 | |||
| 33 | print(data_store) | ||
| 34 | print(sorted(data_store["values"].keys())) | ||
| 35 | |||
| 36 | value = 0.0 | ||
| 37 | new_prec = 4.32 | ||
| 38 | |||
| 39 | x1 = -1.0 | ||
| 40 | x2 = -1.0 | ||
| 41 | y1 = -1.0 | ||
| 42 | y2 = -1.0 | ||
| 43 | u_sort_keys = sorted(data_store["values"].keys(), reverse=True) | ||
| 44 | sort_keys = sorted(data_store["values"].keys(), reverse=False) | ||
| 45 | |||
| 46 | if new_prec > data_store["max_prec"]: | ||
| 47 | x1 = u_sort_keys[1] | ||
| 48 | x2 = u_sort_keys[0] | ||
| 49 | data_store["max_prec"] = new_prec | ||
| 50 | else: | ||
| 51 | if new_prec in sort_keys: | ||
| 52 | value = data_store["values"][new_prec] | ||
| 53 | print(value) | ||
| 54 | exit() | ||
| 55 | else: | ||
| 56 | counter = 0 | ||
| 57 | for key in sort_keys: | ||
| 58 | if key > new_prec: | ||
| 59 | x1 = sort_keys[counter-1] | ||
| 60 | x2 = key | ||
| 61 | break | ||
| 62 | counter = counter + 1 | ||
| 63 | |||
| 64 | y1 = data_store["values"][x1] | ||
| 65 | y2 = data_store["values"][x2] | ||
| 66 | |||
| 67 | value = ((x2 * y1 - x1 * y2) / (x2 - x1)) - (y1 - y2) * new_prec | ||
| 68 | print(value) | ||
| 69 | |||
| 70 | |||
| 71 | |||
| 72 | |||
| 73 | |||
| 74 | #print("{}|{}^^{}|{}".format(x1, y1, x2, y2)) | ||
| 75 | # | ||
| 76 | |||
| 77 | |||
| 78 |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | |||
| 10 | png_path = r"d:\PYTHON\tests\test1\png" | ||
| 11 | |||
| 12 | lenght_lan = 79497.3714882 | ||
| 13 | lenght_lon = 111162.6 | ||
| 14 | base_pixel_len = 152.8740566 | ||
| 15 | str_limiter = '||' | ||
| 16 | |||
| 17 | d1plan_g = base_pixel_len / lenght_lan | ||
| 18 | d1plon_g = base_pixel_len / lenght_lon | ||
| 19 | x286lon = 38.72287 | ||
| 20 | x286lan = 44.417242 | ||
| 21 | |||
| 22 | base_lon = x286lon - (128 * d1plon_g) | ||
| 23 | min_lon = x286lon - (128 * d1plon_g) | ||
| 24 | max_lon = x286lon + (128 * d1plon_g) | ||
| 25 | |||
| 26 | base_lan = x286lan + (128 * d1plan_g) | ||
| 27 | min_lan = x286lan - (128 * d1plan_g) | ||
| 28 | max_lan = x286lan + (128 * d1plan_g) | ||
| 29 | |||
| 30 | pol_store = [] | ||
| 31 | prec_meas = [] | ||
| 32 | |||
| 33 | # Генерировать измерители всех типов | ||
| 34 | def GenerateMeasurements(): | ||
| 35 | |||
| 36 | #l_dlan = d1plan_g * 48 | ||
| 37 | #l_dlon = d1plon_g * 48 | ||
| 38 | |||
| 39 | # Точки для полигонов | ||
| 40 | result = [] | ||
| 41 | result.append(GetMeas(0, 'TEST_00', x286lan, x286lon)) | ||
| 42 | result.append(GetMeas(1, 'TEST_01', 44.3251277777778, 38.6788694444444)) | ||
| 43 | result.append(GetMeas(2, 'TEST_02', 44.3727555555556, 38.7005)) | ||
| 44 | result.append(GetMeas(3, 'TEST_03', 44.4186305555556, 38.6651361111111)) | ||
| 45 | result.append(GetMeas(4, 'TEST_04', 44.4545888888889, 38.6328638888889)) | ||
| 46 | result.append(GetMeas(5, 'TEST_05', 44.4508222222222, 38.6833333333333)) | ||
| 47 | result.append(GetMeas(6, 'TEST_06', 44.4329277777778, 38.7327722222222)) | ||
| 48 | result.append(GetMeas(7, 'TEST_07', 44.4106166666667, 38.7633277777778)) | ||
| 49 | result.append(GetMeas(8, 'TEST_08', 44.3846138888889, 38.7533722222222)) | ||
| 50 | result.append(GetMeas(9, 'TEST_09', 44.3416583333333, 38.735175)) | ||
| 51 | |||
| 52 | prec_meas.append(GetMeas(5, 'X286|s0_d0', x286lan+0, x286lon-0)) | ||
| 53 | |||
| 54 | pol_store.append(GeneratePolygons([result[0], result[3], result[4], result[5], result[6]], 1, "Verh")) | ||
| 55 | pol_store.append(GeneratePolygons([result[0], result[6], result[7], result[8], result[9], result[1], result[2]], 2, "Nige_Polkovnichego")) | ||
| 56 | |||
| 57 | return | ||
| 58 | |||
| 59 | # получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы | ||
| 60 | def GetMeas(_number, _name, _lan, _lon): | ||
| 61 | if _lan <= min_lan or _lan >= max_lan: | ||
| 62 | print("MeasUnit named {} have not current lan ({})".format(_name, _lan)) | ||
| 63 | return None | ||
| 64 | if _lon <= min_lon or _lon >= max_lon: | ||
| 65 | print("MeasUnit named {} have not current lon ({})".format(_name, _lon)) | ||
| 66 | return None | ||
| 67 | |||
| 68 | lan_delta = _lan - base_lan | ||
| 69 | lon_delta = _lon - base_lon | ||
| 70 | |||
| 71 | y_delta = lan_delta * lenght_lan | ||
| 72 | x_delta = lon_delta * lenght_lon | ||
| 73 | |||
| 74 | my = y_delta // base_pixel_len | ||
| 75 | mx = x_delta // base_pixel_len | ||
| 76 | |||
| 77 | result = dict(number = _number, name = _name, x = abs(mx), y = abs(my)) | ||
| 78 | return result | ||
| 79 | |||
| 80 | # Получить осадки по значению dbZ | ||
| 81 | def GetPrecByDBZ_2(_dbz): | ||
| 82 | result = 0 | ||
| 83 | |||
| 84 | if _dbz == 0 or _dbz > 127: | ||
| 85 | return result | ||
| 86 | |||
| 87 | step1 = (_dbz - 32) / 10 | ||
| 88 | step2 = 10 ** step1 | ||
| 89 | step3 = step2 / 200 | ||
| 90 | step4 = step3 ** 0.625 | ||
| 91 | result = step4 | ||
| 92 | return result | ||
| 93 | |||
| 94 | # Сгенерировать полигон по набору геокоординат | ||
| 95 | def GeneratePolygons(_meas_list, _number, _name): | ||
| 96 | # Максимальные значения координат Х и У для полигона | ||
| 97 | max_x = 0 | ||
| 98 | max_y = 0 | ||
| 99 | min_x = 256 | ||
| 100 | min_y = 256 | ||
| 101 | |||
| 102 | #Временный полигон | ||
| 103 | tmp_pol = [] | ||
| 104 | |||
| 105 | # Перебрать измерители последовательно и сформировать полигон как набор пар (х, у) плюс данные о границах полигона (прямоугольных) | ||
| 106 | for imeas in _meas_list: | ||
| 107 | mx =imeas["x"] | ||
| 108 | my = imeas["y"] | ||
| 109 | # Ищем прямоугольные границы полигона | ||
| 110 | if mx > max_x: | ||
| 111 | max_x = mx | ||
| 112 | if my > max_y: | ||
| 113 | max_y = my | ||
| 114 | if mx < min_x: | ||
| 115 | min_x = mx | ||
| 116 | if my < min_y: | ||
| 117 | min_y = my | ||
| 118 | tmp_pol.append((mx, my)) | ||
| 119 | |||
| 120 | 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) | ||
| 121 | result["pol"] = tmp_pol | ||
| 122 | return result | ||
| 123 | |||
| 124 | # Получить "обрезанную" матрицу по полигону | ||
| 125 | def GetCuttedMatrix(_image, _mpolygon): | ||
| 126 | matrix = _mpolygon["pol"] | ||
| 127 | max_x = int(_mpolygon["max_x"]) | ||
| 128 | max_y = int(_mpolygon["max_y"]) | ||
| 129 | min_x = int(_mpolygon["min_x"]) | ||
| 130 | min_y = int(_mpolygon["min_y"]) | ||
| 131 | mask = np.zeros(_image.shape, dtype=np.uint8) | ||
| 132 | roi_corners = np.array([matrix], dtype=np.int32) | ||
| 133 | channel_count = _image.shape[2] # i.e. 3 or 4 depending on your image | ||
| 134 | ignore_mask_color = (255,)*channel_count | ||
| 135 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 136 | masked_image = cv2.bitwise_and(_image, mask) | ||
| 137 | masked_image = masked_image[min_y:max_y, min_x:max_x] | ||
| 138 | return masked_image | ||
| 139 | |||
| 140 | |||
| 141 | # Получаем все файлы из директории с сохранёнными изображениями | ||
| 142 | png_files = os.listdir(png_path) | ||
| 143 | print(png_files) | ||
| 144 | print("Lan border = {} - {}".format(min_lan, max_lan)) | ||
| 145 | print("Lon border = {} - {}".format(min_lon, max_lon)) | ||
| 146 | |||
| 147 | # Сформировать массив "матрица картинки-время" (время из названия файла) | ||
| 148 | store = [] | ||
| 149 | for png_f in png_files: | ||
| 150 | dt_value = png_f.replace('dj_286m_', '').replace('.png', '') | ||
| 151 | dt_value = int(dt_value) | ||
| 152 | dt_value = datetime.datetime.fromtimestamp(dt_value) | ||
| 153 | date_diff = datetime.timedelta(hours=0) | ||
| 154 | dt_value = dt_value + date_diff | ||
| 155 | file_data = imread(png_path + '\\' + png_f) | ||
| 156 | st_unit = dict( | ||
| 157 | datetime = dt_value, | ||
| 158 | matrix = file_data | ||
| 159 | ) | ||
| 160 | store.append(st_unit) | ||
| 161 | |||
| 162 | # Генерируем измерители | ||
| 163 | GenerateMeasurements() | ||
| 164 | |||
| 165 | # Формируем данные | ||
| 166 | main_data = "Дата||АГК-286М||АГК-34||РАД-286М||RAD286(cor)||Сумма верх||Сумма верх(кор)||Объём верх||Объём верх(кор)||Сумма низ||Сумма низ(кор)||Объём низ||Объём низ(кор)\n" | ||
| 167 | |||
| 168 | # Последниё интервал расчёта | ||
| 169 | last_datetime = store[0]["datetime"] | ||
| 170 | |||
| 171 | # Дельта (служебная) между интервалами расчёта | ||
| 172 | dt = datetime.timedelta(minutes=10) | ||
| 173 | |||
| 174 | # Интервал времени | ||
| 175 | datetime_min = datetime.datetime(2020, 1, 29, 22, 50, 0) | ||
| 176 | datetime_max = datetime.datetime(2020, 2, 4, 15, 40, 0) | ||
| 177 | |||
| 178 | # Реальные 286М и 34 | ||
| 179 | real286 = loca_data.GetPrec286M() | ||
| 180 | real34 = loca_data.GetLevel34() | ||
| 181 | # Пробегаемся по всем датам в хранилище реальных осадков | ||
| 182 | for rdata_key in real286.keys(): | ||
| 183 | |||
| 184 | koef_multy_re_d_rad = 1 | ||
| 185 | koef_addit_re_m_rad = 0 | ||
| 186 | prec_data = None | ||
| 187 | lmatrix = None | ||
| 188 | ldatetime = rdata_key | ||
| 189 | print(ldatetime) | ||
| 190 | local_data = "" | ||
| 191 | local_data += ldatetime.__str__() + str_limiter | ||
| 192 | |||
| 193 | # 0. Осадки реальные | ||
| 194 | real_prec = real286[rdata_key] | ||
| 195 | local_data += real_prec.__str__() + str_limiter | ||
| 196 | |||
| 197 | # 0.1 Уровень реальный реальные | ||
| 198 | real_level = real34[rdata_key] | ||
| 199 | local_data += real_level.__str__() + str_limiter | ||
| 200 | |||
| 201 | |||
| 202 | for imgmatrix in store: | ||
| 203 | if imgmatrix["datetime"] == rdata_key: | ||
| 204 | lmatrix = imgmatrix["matrix"] | ||
| 205 | |||
| 206 | if lmatrix is None: | ||
| 207 | local_data += "0||0||0||0||0||0||0||0||0||0||" | ||
| 208 | main_data += local_data + "\n" | ||
| 209 | continue | ||
| 210 | |||
| 211 | # 1. Расчёт осадков по координатам | ||
| 212 | # Формируем для каждого измерителя оасдки в точке, согласно его прямоугольным координатам относительно картинки | ||
| 213 | mes = prec_meas[0] | ||
| 214 | y = int(mes["y"]) | ||
| 215 | x = int(mes["x"]) | ||
| 216 | value = lmatrix[y][x][0] | ||
| 217 | dmrl_prec = GetPrecByDBZ_2(value) | ||
| 218 | dmrl_prec = dmrl_prec / 6 | ||
| 219 | local_data += dmrl_prec.__str__() + str_limiter | ||
| 220 | |||
| 221 | # 1.1 Считаем коэффициенты | ||
| 222 | if dmrl_prec > 0 and real_prec > 0: | ||
| 223 | koef_multy_re_d_rad = real_prec / dmrl_prec | ||
| 224 | koef_addit_re_m_rad = 0 | ||
| 225 | elif dmrl_prec == 0 and real_prec > 0: | ||
| 226 | koef_multy_re_d_rad = 1 | ||
| 227 | koef_addit_re_m_rad = real_prec - dmrl_prec | ||
| 228 | elif dmrl_prec > 0 and real_prec == 0: | ||
| 229 | koef_multy_re_d_rad = 1 | ||
| 230 | koef_addit_re_m_rad = 0 | ||
| 231 | |||
| 232 | #local_data += koef_multy_re_d_rad.__str__() + str_limiter | ||
| 233 | #local_data += koef_addit_re_m_rad.__str__() + str_limiter | ||
| 234 | |||
| 235 | # 1.2 Считаем осадки после корректировки | ||
| 236 | dmrl_prec_cor = (dmrl_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad | ||
| 237 | local_data += dmrl_prec_cor.__str__() + str_limiter | ||
| 238 | |||
| 239 | # 2. Расчет площадей и осадков на площадях | ||
| 240 | for pol in pol_store: | ||
| 241 | masked_image = GetCuttedMatrix(lmatrix, pol) | ||
| 242 | sum_prec = 0 | ||
| 243 | sum_squere = 0 | ||
| 244 | sum_prec_cor = 0 | ||
| 245 | vol_water = 0 | ||
| 246 | vol_water_cor = 0 | ||
| 247 | for yy in masked_image: | ||
| 248 | for xx in yy: | ||
| 249 | lm_value = xx[0] | ||
| 250 | m_prec = GetPrecByDBZ_2(lm_value) | ||
| 251 | m_prec = m_prec / 6 | ||
| 252 | |||
| 253 | if m_prec > 0: | ||
| 254 | sum_squere += 1 | ||
| 255 | |||
| 256 | sum_prec += m_prec | ||
| 257 | |||
| 258 | m_prec_cor = ((m_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad) | ||
| 259 | sum_prec_cor = sum_prec_cor + m_prec_cor | ||
| 260 | |||
| 261 | vol_local = base_pixel_len * base_pixel_len * 1/1000 * m_prec | ||
| 262 | vol_water += vol_local | ||
| 263 | |||
| 264 | vol_local_cor = base_pixel_len * base_pixel_len * 1/1000 * m_prec_cor | ||
| 265 | vol_water_cor += vol_local_cor | ||
| 266 | |||
| 267 | |||
| 268 | local_data += sum_prec.__str__() + str_limiter | ||
| 269 | local_data += sum_prec_cor.__str__() + str_limiter | ||
| 270 | local_data += vol_water.__str__() + str_limiter | ||
| 271 | local_data += vol_water_cor.__str__() + str_limiter | ||
| 272 | #local_data += sum_squere.__str__() + str_limiter | ||
| 273 | |||
| 274 | # Вываливаем данные | ||
| 275 | main_data += local_data + "\n" | ||
| 276 | |||
| 277 | # Заменяем временные разделители и прочие символы для правильного отобраежния в Эксель | ||
| 278 | main_data = main_data.replace("||", "\t") | ||
| 279 | #main_data = main_data.replace(".", ",") | ||
| 280 | |||
| 281 | # Пишем результат в текстовый файл | ||
| 282 | f = open('result.txt', 'w') | ||
| 283 | f.write(main_data) | ||
| 284 | f.close() | ||
| 285 | |||
| 286 | |||
| 287 | """ | ||
| 288 | 1. Для каждого измерителя ищем разницу в широте и долготе лот базовых координат | ||
| 289 | 1.1 Проверяем на выход за предельные значения | ||
| 290 | 2. По здначениям дельты и длинам градусов ищем разницу в метрах | ||
| 291 | 3. По разнице в метрах и базовому размеру пикселя ищем нужный квадрат как количество целых делений дельты в метрах на базовую длину градуса | ||
| 292 | """ | ||
| 293 |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | |||
| 13 | |||
| 14 | png_path = r"d:\PYTHON\tests\test1\png" | ||
| 15 | |||
| 16 | lenght_lan = 79497.3714882 | ||
| 17 | lenght_lon = 111162.6 | ||
| 18 | base_pixel_len = 152.8740566 | ||
| 19 | str_limiter = '||' | ||
| 20 | |||
| 21 | d1plan_g = base_pixel_len / lenght_lan | ||
| 22 | d1plon_g = base_pixel_len / lenght_lon | ||
| 23 | x286lon = 38.72287 | ||
| 24 | x286lan = 44.417242 | ||
| 25 | |||
| 26 | |||
| 27 | base_lon = x286lon - (128 * d1plon_g) | ||
| 28 | min_lon = x286lon - (128 * d1plon_g) | ||
| 29 | max_lon = x286lon + (128 * d1plon_g) | ||
| 30 | |||
| 31 | base_lan = x286lan + (128 * d1plan_g) | ||
| 32 | min_lan = x286lan - (128 * d1plan_g) | ||
| 33 | max_lan = x286lan + (128 * d1plan_g) | ||
| 34 | |||
| 35 | pol_store = [] | ||
| 36 | prec_meas = [] | ||
| 37 | |||
| 38 | 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) | ||
| 39 | 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) | ||
| 40 | flow_rate = duamel_model.CatchmentArea(_capacity=22.2, _in_filter=1.0, _out_filter=0.09) | ||
| 41 | flow_rate1 = duamel_model.CatchmentArea(_capacity=100.0, _in_filter=2.0, _out_filter=0.09) | ||
| 42 | 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) | ||
| 43 | 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) | ||
| 44 | |||
| 45 | # Генерировать измерители всех типов | ||
| 46 | def GenerateMeasurements(): | ||
| 47 | |||
| 48 | # Точки для полигонов | ||
| 49 | result = [] | ||
| 50 | all_result = [] | ||
| 51 | |||
| 52 | # Получение координат полигона водосбора Джубги | ||
| 53 | pcs = loca_data.GetGeoCoordPolygon() | ||
| 54 | |||
| 55 | # Последняя запись - для отбрасывания дублей пикселей | ||
| 56 | p_last = dict(x = -1.0, y = 0.0) | ||
| 57 | |||
| 58 | # Получаем список точек полигона | ||
| 59 | for pc in pcs: | ||
| 60 | p = GetMeas(pc[0], pc[1], pc[2], pc[3]) | ||
| 61 | |||
| 62 | if p_last['x'] == -1.0: | ||
| 63 | p_last['x'] = p['x'] | ||
| 64 | p_last['y'] = p['y'] | ||
| 65 | all_result.append(p) | ||
| 66 | else: | ||
| 67 | if p_last['x'] != p['x'] and p_last['y'] != p['y']: | ||
| 68 | all_result.append(p) | ||
| 69 | |||
| 70 | p_last['x'] = p['x'] | ||
| 71 | p_last['y'] = p['y'] | ||
| 72 | |||
| 73 | result.append(GetMeas(0, 'TEST_00', x286lan, x286lon)) | ||
| 74 | result.append(GetMeas(1, 'TEST_01', 44.3251277777778, 38.6788694444444)) | ||
| 75 | result.append(GetMeas(2, 'TEST_02', 44.3727555555556, 38.7005)) | ||
| 76 | result.append(GetMeas(3, 'TEST_03', 44.4186305555556, 38.6651361111111)) | ||
| 77 | result.append(GetMeas(4, 'TEST_04', 44.4545888888889, 38.6328638888889)) | ||
| 78 | result.append(GetMeas(5, 'TEST_05', 44.4508222222222, 38.6833333333333)) | ||
| 79 | result.append(GetMeas(6, 'TEST_06', 44.4329277777778, 38.7327722222222)) | ||
| 80 | result.append(GetMeas(7, 'TEST_07', 44.4106166666667, 38.7633277777778)) | ||
| 81 | result.append(GetMeas(8, 'TEST_08', 44.3846138888889, 38.7533722222222)) | ||
| 82 | result.append(GetMeas(9, 'TEST_09', 44.3416583333333, 38.735175)) | ||
| 83 | |||
| 84 | prec_meas.append(GetMeas(5, 'X286|s0_d0', x286lan+0, x286lon-0)) | ||
| 85 | |||
| 86 | pol_store.append(GeneratePolygons(all_result, 0, "All")) | ||
| 87 | #pol_store.append(GeneratePolygons([result[0], result[3], result[4], result[5], result[6]], 1, "Verh")) | ||
| 88 | #pol_store.append(GeneratePolygons([result[0], result[6], result[7], result[8], result[9], result[1], result[2]], 2, "Nige_Polkovnichego")) | ||
| 89 | |||
| 90 | return | ||
| 91 | |||
| 92 | # получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы | ||
| 93 | def GetMeas(_number, _name, _lan, _lon): | ||
| 94 | if _lan <= min_lan or _lan >= max_lan: | ||
| 95 | print("MeasUnit named {} have not current lan ({})".format(_name, _lan)) | ||
| 96 | return None | ||
| 97 | if _lon <= min_lon or _lon >= max_lon: | ||
| 98 | print("MeasUnit named {} have not current lon ({})".format(_name, _lon)) | ||
| 99 | return None | ||
| 100 | |||
| 101 | lan_delta = _lan - base_lan | ||
| 102 | lon_delta = _lon - base_lon | ||
| 103 | |||
| 104 | y_delta = lan_delta * lenght_lan | ||
| 105 | x_delta = lon_delta * lenght_lon | ||
| 106 | |||
| 107 | my = y_delta // base_pixel_len | ||
| 108 | mx = x_delta // base_pixel_len | ||
| 109 | |||
| 110 | result = dict(number = _number, name = _name, x = abs(mx), y = abs(my)) | ||
| 111 | return result | ||
| 112 | |||
| 113 | # Получить осадки по значению dbZ | ||
| 114 | def GetPrecByDBZ_2(_dbz): | ||
| 115 | result = 0 | ||
| 116 | |||
| 117 | if _dbz == 0 or _dbz > 127: | ||
| 118 | return result | ||
| 119 | |||
| 120 | step1 = (_dbz - 32) / 10 | ||
| 121 | step2 = 10 ** step1 | ||
| 122 | step3 = step2 / 200 | ||
| 123 | step4 = step3 ** 0.625 | ||
| 124 | result = step4 | ||
| 125 | return result | ||
| 126 | |||
| 127 | # Сгенерировать полигон по набору геокоординат | ||
| 128 | def GeneratePolygons(_meas_list, _number, _name): | ||
| 129 | # Максимальные значения координат Х и У для полигона | ||
| 130 | max_x = 0 | ||
| 131 | max_y = 0 | ||
| 132 | min_x = 256 | ||
| 133 | min_y = 256 | ||
| 134 | |||
| 135 | #Временный полигон | ||
| 136 | tmp_pol = [] | ||
| 137 | |||
| 138 | # Перебрать измерители последовательно и сформировать полигон как набор пар (х, у) плюс данные о границах полигона (прямоугольных) | ||
| 139 | for imeas in _meas_list: | ||
| 140 | mx =imeas["x"] | ||
| 141 | my = imeas["y"] | ||
| 142 | # Ищем прямоугольные границы полигона | ||
| 143 | if mx > max_x: | ||
| 144 | max_x = mx | ||
| 145 | if my > max_y: | ||
| 146 | max_y = my | ||
| 147 | if mx < min_x: | ||
| 148 | min_x = mx | ||
| 149 | if my < min_y: | ||
| 150 | min_y = my | ||
| 151 | tmp_pol.append((mx, my)) | ||
| 152 | |||
| 153 | 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) | ||
| 154 | result["pol"] = tmp_pol | ||
| 155 | return result | ||
| 156 | |||
| 157 | # Получить "обрезанную" матрицу по полигону | ||
| 158 | def GetCuttedMatrix(_image, _mpolygon): | ||
| 159 | matrix = _mpolygon["pol"] | ||
| 160 | max_x = int(_mpolygon["max_x"]) | ||
| 161 | max_y = int(_mpolygon["max_y"]) | ||
| 162 | min_x = int(_mpolygon["min_x"]) | ||
| 163 | min_y = int(_mpolygon["min_y"]) | ||
| 164 | |||
| 165 | mask = np.zeros(_image.shape, dtype=np.uint8) | ||
| 166 | roi_corners = np.array([matrix], dtype=np.int32) | ||
| 167 | channel_count = _image.shape[2] # i.e. 3 or 4 depending on your image | ||
| 168 | ignore_mask_color = (255,)*channel_count | ||
| 169 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 170 | masked_image = cv2.bitwise_and(_image, mask) | ||
| 171 | masked_image = masked_image[min_y:max_y, min_x:max_x] | ||
| 172 | return masked_image | ||
| 173 | |||
| 174 | |||
| 175 | # Получаем все файлы из директории с сохранёнными изображениями | ||
| 176 | png_files = os.listdir(png_path) | ||
| 177 | print(png_files) | ||
| 178 | print("Lan border = {} - {}".format(min_lan, max_lan)) | ||
| 179 | print("Lon border = {} - {}".format(min_lon, max_lon)) | ||
| 180 | |||
| 181 | # Сформировать массив "матрица картинки-время" (время из названия файла) | ||
| 182 | store = [] | ||
| 183 | for png_f in png_files: | ||
| 184 | dt_value = png_f.replace('dj_286m_', '').replace('.png', '') | ||
| 185 | dt_value = int(dt_value) | ||
| 186 | dt_value = datetime.datetime.fromtimestamp(dt_value) | ||
| 187 | date_diff = datetime.timedelta(hours=0) | ||
| 188 | dt_value = dt_value + date_diff | ||
| 189 | file_data = imread(png_path + '\\' + png_f) | ||
| 190 | st_unit = dict( | ||
| 191 | datetime = dt_value, | ||
| 192 | matrix = file_data | ||
| 193 | ) | ||
| 194 | |||
| 195 | store.append(st_unit) | ||
| 196 | |||
| 197 | # Генерируем измерители | ||
| 198 | GenerateMeasurements() | ||
| 199 | |||
| 200 | # Формируем данные | ||
| 201 | main_data = "Дата||АГК-286М||АГК-34||РАД-286М||RAD286(cor)||Сумма ВСЕГО||Сумма ВСЕГО(кор)||Сумма ВСЕГО ОБ||Сумма ВСЕГО ОБ(кор)||Flow||Duamel||DuamLevel||\n" | ||
| 202 | |||
| 203 | # Последниё интервал расчёта | ||
| 204 | last_datetime = store[0]["datetime"] | ||
| 205 | |||
| 206 | # Дельта (служебная) между интервалами расчёта | ||
| 207 | dt = datetime.timedelta(minutes=10) | ||
| 208 | |||
| 209 | # Интервал времени | ||
| 210 | datetime_min = datetime.datetime(2020, 1, 29, 22, 50, 0) | ||
| 211 | datetime_max = datetime.datetime(2020, 2, 4, 15, 40, 0) | ||
| 212 | |||
| 213 | # Реальные 286М и 34 | ||
| 214 | real286 = loca_data.GetPrec286M() | ||
| 215 | real34 = loca_data.GetLevel34() | ||
| 216 | |||
| 217 | dtcounter = -1 | ||
| 218 | |||
| 219 | # Для графиков | ||
| 220 | mas_x = [] #time | ||
| 221 | mas_real = [] #real water level | ||
| 222 | mas_duam = [] #duamel water level | ||
| 223 | mas_duam1 = [] #duamel water level | ||
| 224 | mas_sher_duam = [] #дюамель от шержукова | ||
| 225 | mas_wvol = [] #water volume | ||
| 226 | |||
| 227 | # Пробегаемся по всем датам в хранилище реальных осадков | ||
| 228 | for rdata_key in real286.keys(): | ||
| 229 | |||
| 230 | dtcounter = dtcounter + 1 | ||
| 231 | mas_x.append(dtcounter) | ||
| 232 | |||
| 233 | koef_multy_re_d_rad = 1 | ||
| 234 | koef_addit_re_m_rad = 0 | ||
| 235 | prec_data = None | ||
| 236 | lmatrix = None | ||
| 237 | ldatetime = rdata_key | ||
| 238 | print(ldatetime) | ||
| 239 | local_data = "" | ||
| 240 | local_data += ldatetime.__str__() + str_limiter | ||
| 241 | |||
| 242 | # 0. Осадки реальные | ||
| 243 | real_prec = real286[rdata_key] | ||
| 244 | local_data += real_prec.__str__() + str_limiter | ||
| 245 | |||
| 246 | # 0.1 Уровень реальный | ||
| 247 | real_level = real34[rdata_key] | ||
| 248 | local_data += real_level.__str__() + str_limiter | ||
| 249 | mas_real.append(real_level) | ||
| 250 | |||
| 251 | for imgmatrix in store: | ||
| 252 | if imgmatrix["datetime"] == rdata_key: | ||
| 253 | lmatrix = imgmatrix["matrix"] | ||
| 254 | |||
| 255 | if lmatrix is None: | ||
| 256 | local_data += "0||0||0||0||" | ||
| 257 | rain_corr = real_prec | ||
| 258 | flow = flow_rate.calc_surface_flow(rain_corr) | ||
| 259 | flow1 = flow_rate1.calc_surface_flow(rain_corr) | ||
| 260 | |||
| 261 | duam_value = duamel.model_step(dtcounter, flow) | ||
| 262 | duam_valk1 = duamelk1.model_step(dtcounter, flow) | ||
| 263 | |||
| 264 | wlevel = level_calc.bs_water_level(duam_value) | ||
| 265 | wlevel1 = level_calc.bs_water_level(duam_valk1) | ||
| 266 | |||
| 267 | mas_duam.append(wlevel) | ||
| 268 | mas_duam1.append(wlevel1) | ||
| 269 | |||
| 270 | test_sher_level = sher_duam.CalculateLevel(rain_corr, dtcounter) | ||
| 271 | mas_sher_duam.append(test_sher_level) | ||
| 272 | |||
| 273 | mas_wvol.append(0.0) | ||
| 274 | |||
| 275 | local_data += flow.__str__() + str_limiter | ||
| 276 | local_data += duam_value.__str__() + str_limiter | ||
| 277 | local_data += wlevel.__str__() + str_limiter | ||
| 278 | |||
| 279 | main_data += local_data + "\n" | ||
| 280 | continue | ||
| 281 | |||
| 282 | # 1. Расчёт осадков по координатам | ||
| 283 | # Формируем для каждого измерителя оасдки в точке, согласно его прямоугольным координатам относительно картинки | ||
| 284 | mes = prec_meas[0] | ||
| 285 | y = int(mes["y"]) | ||
| 286 | x = int(mes["x"]) | ||
| 287 | value = lmatrix[y][x][0] | ||
| 288 | dmrl_prec = GetPrecByDBZ_2(value) | ||
| 289 | dmrl_prec = dmrl_prec / 6 | ||
| 290 | local_data += dmrl_prec.__str__() + str_limiter | ||
| 291 | |||
| 292 | # 1.1 Считаем коэффициенты | ||
| 293 | if dmrl_prec > 0 and real_prec > 0: | ||
| 294 | koef_multy_re_d_rad = real_prec / dmrl_prec | ||
| 295 | koef_addit_re_m_rad = 0 | ||
| 296 | elif dmrl_prec == 0 and real_prec > 0: | ||
| 297 | koef_multy_re_d_rad = 1 | ||
| 298 | koef_addit_re_m_rad = real_prec - dmrl_prec | ||
| 299 | elif dmrl_prec > 0 and real_prec == 0: | ||
| 300 | koef_multy_re_d_rad = 1 | ||
| 301 | koef_addit_re_m_rad = 0 | ||
| 302 | |||
| 303 | # 1.2 Считаем осадки после корректировки | ||
| 304 | dmrl_prec_cor = (dmrl_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad | ||
| 305 | local_data += dmrl_prec_cor.__str__() + str_limiter | ||
| 306 | |||
| 307 | # 2. Расчет площадей и осадков на площадях | ||
| 308 | |||
| 309 | for pol in pol_store: | ||
| 310 | masked_image = GetCuttedMatrix(lmatrix, pol) | ||
| 311 | sum_prec = 0 | ||
| 312 | sum_squere = 0 | ||
| 313 | sum_prec_cor = 0 | ||
| 314 | vol_water = 0 | ||
| 315 | vol_water_cor = 0 | ||
| 316 | for yy in masked_image: | ||
| 317 | for xx in yy: | ||
| 318 | lm_value = xx[0] | ||
| 319 | m_prec = GetPrecByDBZ_2(lm_value) | ||
| 320 | m_prec = m_prec / 6 | ||
| 321 | |||
| 322 | if m_prec > 0: | ||
| 323 | sum_squere += 1 | ||
| 324 | |||
| 325 | sum_prec += m_prec | ||
| 326 | |||
| 327 | m_prec_cor = ((m_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad) | ||
| 328 | sum_prec_cor = sum_prec_cor + m_prec_cor | ||
| 329 | |||
| 330 | vol_local = base_pixel_len * base_pixel_len * 1/1000 * m_prec | ||
| 331 | vol_water += vol_local | ||
| 332 | |||
| 333 | vol_local_cor = base_pixel_len * base_pixel_len * 1/1000 * m_prec_cor | ||
| 334 | vol_water_cor += vol_local_cor | ||
| 335 | |||
| 336 | |||
| 337 | local_data += sum_prec.__str__() + str_limiter | ||
| 338 | local_data += sum_prec_cor.__str__() + str_limiter | ||
| 339 | local_data += vol_water.__str__() + str_limiter | ||
| 340 | local_data += vol_water_cor.__str__() + str_limiter | ||
| 341 | |||
| 342 | rain_corr = vol_water * 0.0000099471691 * 8 | ||
| 343 | mas_wvol.append(rain_corr) | ||
| 344 | |||
| 345 | flow = flow_rate.calc_surface_flow(rain_corr) | ||
| 346 | flow1 = flow_rate1.calc_surface_flow(rain_corr) | ||
| 347 | |||
| 348 | duam_value = duamel.model_step(dtcounter, flow) | ||
| 349 | duam_valk1 = duamelk1.model_step(dtcounter, flow) | ||
| 350 | |||
| 351 | wlevel = level_calc.bs_water_level(duam_value) | ||
| 352 | wlevel1 = level_calc.bs_water_level(duam_valk1) | ||
| 353 | |||
| 354 | test_sher_level = sher_duam.CalculateLevel(flow1, dtcounter) | ||
| 355 | |||
| 356 | mas_duam.append(wlevel) | ||
| 357 | mas_duam1.append(wlevel1) | ||
| 358 | mas_sher_duam.append(test_sher_level) | ||
| 359 | |||
| 360 | local_data += flow.__str__() + str_limiter | ||
| 361 | local_data += duam_value.__str__() + str_limiter | ||
| 362 | local_data += wlevel.__str__() + str_limiter | ||
| 363 | |||
| 364 | local_data += sum_squere.__str__() + str_limiter | ||
| 365 | |||
| 366 | #local_data += sum_squere.__str__() + str_limiter | ||
| 367 | |||
| 368 | # Вываливаем данные | ||
| 369 | main_data += local_data + "\n" | ||
| 370 | |||
| 371 | # Заменяем временные разделители и прочие символы для правильного отобраежния в Эксель | ||
| 372 | main_data = main_data.replace("||", "\t") | ||
| 373 | |||
| 374 | # Пишем результат в текстовый файл | ||
| 375 | f = open('result.txt', 'w') | ||
| 376 | f.write(main_data) | ||
| 377 | f.close() | ||
| 378 | |||
| 379 | fig, ax = plt.subplots() | ||
| 380 | |||
| 381 | ax.plot(mas_x, mas_real, label = 'AGK-34') | ||
| 382 | ax.plot(mas_x, mas_duam, label = 'DUAM') | ||
| 383 | ax.plot(mas_x, mas_duam1, label = 'DUAM_2') | ||
| 384 | ax.plot(mas_x, mas_sher_duam, label = 'SHER_DUAM') | ||
| 385 | |||
| 386 | ax.legend() | ||
| 387 | |||
| 388 | plt.show() | ||
| 389 | |||
| 390 | |||
| 391 | |||
| 392 | """ | ||
| 393 | 1. Для каждого измерителя ищем разницу в широте и долготе лот базовых координат | ||
| 394 | 1.1 Проверяем на выход за предельные значения | ||
| 395 | 2. По здначениям дельты и длинам градусов ищем разницу в метрах | ||
| 396 | 3. По разнице в метрах и базовому размеру пикселя ищем нужный квадрат как количество целых делений дельты в метрах на базовую длину градуса | ||
| 397 | """ | ||
| 398 |
| 1 | import cv2 | ||
| 2 | import numpy as np | ||
| 3 | |||
| 4 | # original image | ||
| 5 | # -1 loads as-is so if it will be 3 or 4 channel as the original | ||
| 6 | image = cv2.imread('test.png', -1) | ||
| 7 | # mask defaulting to black for 3-channel and transparent for 4-channel | ||
| 8 | # (of course replace corners with yours) | ||
| 9 | mask = np.zeros(image.shape, dtype=np.uint8) | ||
| 10 | roi_corners = np.array([[(10,10), (20,20), (10,30)]], dtype=np.int32) | ||
| 11 | # fill the ROI so it doesn't get wiped out when the mask is applied | ||
| 12 | channel_count = image.shape[2] # i.e. 3 or 4 depending on your image | ||
| 13 | ignore_mask_color = (255,)*channel_count | ||
| 14 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 15 | # from Masterfool: use cv2.fillConvexPoly if you know it's convex | ||
| 16 | |||
| 17 | # apply the mask | ||
| 18 | masked_image = cv2.bitwise_and(image, mask) | ||
| 19 | |||
| 20 | # save the result | ||
| 21 | cv2.imwrite('image_masked.png', masked_image) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | import dateutil.parser | ||
| 13 | import psycopg2 | ||
| 14 | import pathlib | ||
| 15 | |||
| 16 | |||
| 17 | def get_connection(): | ||
| 18 | DBConnection = psycopg2.connect( | ||
| 19 | host="localhost", | ||
| 20 | port = "15432", | ||
| 21 | database="wf71", | ||
| 22 | user="wf71", | ||
| 23 | password="wf71") | ||
| 24 | print("Connect is success!") | ||
| 25 | DBConnection.autocommit = True | ||
| 26 | return DBConnection | ||
| 27 | |||
| 28 | def write_png(filename = "test.png", px_array = None): | ||
| 29 | if px_array is None: | ||
| 30 | px_array = np.zeros(10,10) | ||
| 31 | path = pathlib.Path(__file__).parent.absolute() | ||
| 32 | path = str(path) + filename | ||
| 33 | cv2.imwrite(path, px_array) | ||
| 34 | |||
| 35 | def get_png_data_from_db(): | ||
| 36 | DBConnection = get_connection() | ||
| 37 | print("Connect is success!") | ||
| 38 | cur = DBConnection.cursor() | ||
| 39 | query = "select measuretime, additional_info from md_precipitation where measurer_uuid = '1bc2b71c-d505-4034-a939-df0252b3f7c6' and measuretime >= '2020-07-08 07:00:00' and measuretime <= '2020-07-09 07:00:00'" | ||
| 40 | cur.execute(query) | ||
| 41 | result = cur.fetchall() | ||
| 42 | radar_a = 200 | ||
| 43 | radar_n = 1.6 | ||
| 44 | for_txt = [] | ||
| 45 | |||
| 46 | for var in result: | ||
| 47 | matrix = [] | ||
| 48 | m_dt = var[0] | ||
| 49 | mx = json.loads(var[1]) | ||
| 50 | value = 0.0 | ||
| 51 | |||
| 52 | error = mx.get("error", False) | ||
| 53 | |||
| 54 | if error == "Radar matrix is not exist": | ||
| 55 | value = 0.0 | ||
| 56 | else: | ||
| 57 | matrix = mx["matrix"] | ||
| 58 | if len(matrix) > 1: | ||
| 59 | _dbz = matrix[143][107] | ||
| 60 | if _dbz == 0 or _dbz > 127: | ||
| 61 | value = 0.0 | ||
| 62 | else: | ||
| 63 | step1 = (_dbz - 32) / 10 | ||
| 64 | step2 = 10 ** step1 | ||
| 65 | step3 = step2 / radar_a | ||
| 66 | step4 = step3 ** (1.0/radar_n) | ||
| 67 | step5 = step4 / 6.0 | ||
| 68 | value = step5 | ||
| 69 | |||
| 70 | #delta_dt = datetime.timedelta(hours=3) | ||
| 71 | #m_dt = datetime.datetime.strptime(str(m_dt), '%Y-%m-%d %H:%M:%S') - delta_dt | ||
| 72 | for_txt.append([str(m_dt), value]) | ||
| 73 | |||
| 74 | cur.close() | ||
| 75 | f = open('result_from_db.txt', 'w') | ||
| 76 | f.write(str(for_txt)) | ||
| 77 | f.close() | ||
| 78 | |||
| 79 | def get_png_picture_from_db(): | ||
| 80 | DBConnection = get_connection() | ||
| 81 | print("Connect is success!") | ||
| 82 | cur = DBConnection.cursor() | ||
| 83 | query = "select measuretime, additional_info from md_precipitation where measurer_uuid = '1bc2b71c-d505-4034-a939-df0252b3f7c6' and measuretime >= '2020-07-08 07:00:00' and measuretime <= '2020-07-09 07:00:00'" | ||
| 84 | cur.execute(query) | ||
| 85 | result = cur.fetchall() | ||
| 86 | i = -1 | ||
| 87 | |||
| 88 | |||
| 89 | for var in result: | ||
| 90 | matrix = [] | ||
| 91 | m_dt = var[0] | ||
| 92 | td = datetime.timedelta(hours=3) | ||
| 93 | m_dt = m_dt+td | ||
| 94 | print(m_dt) | ||
| 95 | mx = json.loads(var[1]) | ||
| 96 | img = np.zeros((256,256, 4),dtype=np.uint8) | ||
| 97 | |||
| 98 | error = mx.get("error", False) | ||
| 99 | |||
| 100 | if error == "Radar matrix is not exist": | ||
| 101 | continue | ||
| 102 | else: | ||
| 103 | matrix = mx["matrix"] | ||
| 104 | if len(matrix) > 1: | ||
| 105 | #png_data = [] | ||
| 106 | #for line in matrix: | ||
| 107 | # new_line = [] | ||
| 108 | # for column in line: | ||
| 109 | # new_line.append([column, column, column, 255]) | ||
| 110 | # png_data.append(new_line) | ||
| 111 | #png_data = np.array(png_data) | ||
| 112 | x = -1 | ||
| 113 | for line in matrix: | ||
| 114 | x = x + 1 | ||
| 115 | y = -1 | ||
| 116 | for column in line: | ||
| 117 | y = y + 1 | ||
| 118 | img[x][y] = [column, column, column, 255] | ||
| 119 | |||
| 120 | fn_dt = '{}_{}_{}__{}_{}.png'.format(m_dt.timetuple()[0], m_dt.timetuple()[1], m_dt.timetuple()[2], m_dt.timetuple()[3], m_dt.timetuple()[4]) | ||
| 121 | #write_png(filename=r"/png_07/{}".format(fn_dt), px_array=png_data) | ||
| 122 | write_png(filename=r"/png_07/{}".format(fn_dt), px_array=img) | ||
| 123 | cur.close() | ||
| 124 | #get_png_picture_from_db | ||
| 125 | |||
| 126 | |||
| 127 | #get_png_data_from_db() | ||
| 128 | get_png_picture_from_db() | ||
| 129 |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | |||
| 13 | |||
| 14 | png_path = r"d:\PYTHON\tests\test1\test_png\dj_286m_1580308200.png" | ||
| 15 | save_path = r"d:\PYTHON\tests\test1\test_png\test.png" | ||
| 16 | |||
| 17 | lenght_lan = 79497.3714882 | ||
| 18 | lenght_lon = 111162.6 | ||
| 19 | base_pixel_len = 152.8740566 | ||
| 20 | str_limiter = '||' | ||
| 21 | |||
| 22 | d1plan_g = base_pixel_len / lenght_lan | ||
| 23 | d1plon_g = base_pixel_len / lenght_lon | ||
| 24 | x286lon = 38.72287 | ||
| 25 | x286lan = 44.417242 | ||
| 26 | |||
| 27 | base_lon = x286lon - (128 * d1plon_g) | ||
| 28 | min_lon = x286lon - (128 * d1plon_g) | ||
| 29 | max_lon = x286lon + (128 * d1plon_g) | ||
| 30 | |||
| 31 | base_lan = x286lan + (128 * d1plan_g) | ||
| 32 | min_lan = x286lan - (128 * d1plan_g) | ||
| 33 | max_lan = x286lan + (128 * d1plan_g) | ||
| 34 | |||
| 35 | pol_store = [] | ||
| 36 | prec_meas = [] | ||
| 37 | |||
| 38 | # Сгенерировать полигон по набору геокоординат | ||
| 39 | def GeneratePolygons(_meas_list, _number, _name): | ||
| 40 | # Максимальные значения координат Х и У для полигона | ||
| 41 | max_x = 0 | ||
| 42 | max_y = 0 | ||
| 43 | min_x = 256 | ||
| 44 | min_y = 256 | ||
| 45 | |||
| 46 | #Временный полигон | ||
| 47 | tmp_pol = [] | ||
| 48 | |||
| 49 | # Перебрать измерители последовательно и сформировать полигон как набор пар (х, у) плюс данные о границах полигона (прямоугольных) | ||
| 50 | for imeas in _meas_list: | ||
| 51 | mx =imeas["x"] | ||
| 52 | my = imeas["y"] | ||
| 53 | # Ищем прямоугольные границы полигона | ||
| 54 | if mx > max_x: | ||
| 55 | max_x = mx | ||
| 56 | if my > max_y: | ||
| 57 | max_y = my | ||
| 58 | if mx < min_x: | ||
| 59 | min_x = mx | ||
| 60 | if my < min_y: | ||
| 61 | min_y = my | ||
| 62 | tmp_pol.append((mx, my)) | ||
| 63 | |||
| 64 | #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) | ||
| 65 | result = tmp_pol | ||
| 66 | return result | ||
| 67 | |||
| 68 | # получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы | ||
| 69 | def GetMeas(_number, _name, _lan, _lon): | ||
| 70 | if _lan <= min_lan or _lan >= max_lan: | ||
| 71 | print("MeasUnit named {} have not current lan ({})".format(_name, _lan)) | ||
| 72 | return None | ||
| 73 | if _lon <= min_lon or _lon >= max_lon: | ||
| 74 | print("MeasUnit named {} have not current lon ({})".format(_name, _lon)) | ||
| 75 | return None | ||
| 76 | |||
| 77 | lan_delta = _lan - base_lan | ||
| 78 | lon_delta = _lon - base_lon | ||
| 79 | |||
| 80 | y_delta = lan_delta * lenght_lan | ||
| 81 | x_delta = lon_delta * lenght_lon | ||
| 82 | |||
| 83 | my = y_delta // base_pixel_len | ||
| 84 | mx = x_delta // base_pixel_len | ||
| 85 | |||
| 86 | result = dict(number = _number, name = _name, x = abs(mx), y = abs(my)) | ||
| 87 | return result | ||
| 88 | |||
| 89 | _image = imread(png_path) | ||
| 90 | |||
| 91 | # Получение координат полигона водосбора Джубги | ||
| 92 | pcs = loca_data.GetGeoCoordPolygon() | ||
| 93 | |||
| 94 | # Последняя запись - для отбрасывания дублей пикселей | ||
| 95 | p_last = dict(x = -1.0, y = 0.0) | ||
| 96 | |||
| 97 | all_result = [] | ||
| 98 | |||
| 99 | # Получаем список точек полигона | ||
| 100 | for pc in pcs: | ||
| 101 | p = GetMeas(pc[0], pc[1], pc[2], pc[3]) | ||
| 102 | |||
| 103 | if p_last['x'] == -1.0: | ||
| 104 | p_last['x'] = p['x'] | ||
| 105 | p_last['y'] = p['y'] | ||
| 106 | all_result.append(p) | ||
| 107 | else: | ||
| 108 | if p_last['x'] != p['x'] and p_last['y'] != p['y']: | ||
| 109 | all_result.append(p) | ||
| 110 | |||
| 111 | p_last['x'] = p['x'] | ||
| 112 | p_last['y'] = p['y'] | ||
| 113 | |||
| 114 | polygon = GeneratePolygons(all_result, 0, "All") | ||
| 115 | #polygon = all_result | ||
| 116 | |||
| 117 | |||
| 118 | ################################################## | ||
| 119 | # пробуем создать пустое изображение и заполнить его полигоном | ||
| 120 | img = np.zeros((256,256,4), np.uint8) | ||
| 121 | |||
| 122 | for yy in img: | ||
| 123 | for xx in yy: | ||
| 124 | xx[0] = 255 | ||
| 125 | xx[1] = 0 | ||
| 126 | xx[2] = 0 | ||
| 127 | xx[3] = 255 | ||
| 128 | |||
| 129 | img_mask = np.zeros(img.shape, dtype=np.uint8) | ||
| 130 | img_roi_corners = np.array([polygon], dtype=np.int32) | ||
| 131 | img_ignore_mask_color = (255,)*4 | ||
| 132 | cv2.fillPoly(img_mask, img_roi_corners, img_ignore_mask_color) | ||
| 133 | img_masked_image = cv2.bitwise_and(img, img_mask) | ||
| 134 | |||
| 135 | cv2.imwrite(save_path, img_masked_image) | ||
| 136 | |||
| 137 | pcx_square_count = 0 | ||
| 138 | |||
| 139 | for yy in img_masked_image: | ||
| 140 | for xx in yy: | ||
| 141 | if xx[0] == 255: | ||
| 142 | pcx_square_count = pcx_square_count + 1 | ||
| 143 | |||
| 144 | print(pcx_square_count) | ||
| 145 | |||
| 146 | squere = base_pixel_len * base_pixel_len * pcx_square_count | ||
| 147 | |||
| 148 | print(squere) | ||
| 149 | |||
| 150 | |||
| 151 | |||
| 152 | ################################################## | ||
| 153 | |||
| 154 | |||
| 155 | '''mask = np.zeros(_image.shape, dtype=np.uint8) | ||
| 156 | |||
| 157 | roi_corners = np.array([polygon], dtype=np.int32) | ||
| 158 | |||
| 159 | channel_count = _image.shape[2] # i.e. 3 or 4 depending on your image | ||
| 160 | |||
| 161 | ignore_mask_color = (255,)*channel_count | ||
| 162 | |||
| 163 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 164 | |||
| 165 | masked_image = cv2.bitwise_and(_image, mask)''' | ||
| 166 | |||
| 167 |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | |||
| 7 | |||
| 8 | png_path = r"d:\PYTHON\tests\test1\png" | ||
| 9 | |||
| 10 | lenght_lan = 79497.3714882 | ||
| 11 | lenght_lon = 111162.6 | ||
| 12 | base_pixel_len = 152.8740566 | ||
| 13 | str_limiter = '||' | ||
| 14 | |||
| 15 | d1plan_g = base_pixel_len / lenght_lan | ||
| 16 | d1plon_g = base_pixel_len / lenght_lon | ||
| 17 | x286lon = 38.72287 | ||
| 18 | x286lan = 44.417242 | ||
| 19 | |||
| 20 | base_lon = x286lon - (128 * d1plon_g) | ||
| 21 | min_lon = x286lon - (128 * d1plon_g) | ||
| 22 | max_lon = x286lon + (128 * d1plon_g) | ||
| 23 | |||
| 24 | base_lan = x286lan + (128 * d1plan_g) | ||
| 25 | min_lan = x286lan - (128 * d1plan_g) | ||
| 26 | max_lan = x286lan + (128 * d1plan_g) | ||
| 27 | |||
| 28 | # Генерировать измерители | ||
| 29 | def GenerateMeasurements(): | ||
| 30 | |||
| 31 | result = [] | ||
| 32 | l_dlan = d1plan_g * 48 | ||
| 33 | l_dlon = d1plon_g * 48 | ||
| 34 | result.append(GetMeas(1, 'X286|sp_dm', x286lan+l_dlan, x286lon-l_dlon)) | ||
| 35 | result.append(GetMeas(2, 'X286|sp_d0', x286lan+l_dlan, x286lon-0)) | ||
| 36 | result.append(GetMeas(3, 'X286|sp_dp', x286lan+l_dlan, x286lon+l_dlon)) | ||
| 37 | result.append(GetMeas(4, 'X286|s0_dm', x286lan+0, x286lon-l_dlon)) | ||
| 38 | result.append(GetMeas(5, 'X286|s0_d0', x286lan+0, x286lon-0)) | ||
| 39 | result.append(GetMeas(6, 'X286|s0_dp', x286lan+0, x286lon+l_dlon)) | ||
| 40 | result.append(GetMeas(7, 'X286|sm_dm', x286lan-l_dlan, x286lon-l_dlon)) | ||
| 41 | result.append(GetMeas(8, 'X286|sm_d0', x286lan-l_dlan, x286lon-0)) | ||
| 42 | result.append(GetMeas(9, 'X286|sm_dp', x286lan-l_dlan, x286lon+l_dlon)) | ||
| 43 | |||
| 44 | ''' | ||
| 45 | result.append(GetMeas(1, 'TEST_01', 44.3251277777778, 38.6788694444444)) | ||
| 46 | result.append(GetMeas(2, 'TEST_02', 44.3727555555556, 38.7005)) | ||
| 47 | result.append(GetMeas(3, 'TEST_03', 44.4186305555556, 38.6651361111111)) | ||
| 48 | result.append(GetMeas(4, 'TEST_04', 44.4545888888889, 38.6328638888889)) | ||
| 49 | result.append(GetMeas(5, 'TEST_05', 44.4508222222222, 38.6833333333333)) | ||
| 50 | result.append(GetMeas(6, 'TEST_06', 44.4329277777778, 38.7327722222222)) | ||
| 51 | result.append(GetMeas(7, 'TEST_07', 44.4106166666667, 38.7633277777778)) | ||
| 52 | result.append(GetMeas(8, 'TEST_08', 44.3846138888889, 38.7533722222222)) | ||
| 53 | result.append(GetMeas(9, 'TEST_09', 44.3416583333333, 38.735175)) | ||
| 54 | ''' | ||
| 55 | |||
| 56 | return result | ||
| 57 | |||
| 58 | # получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы | ||
| 59 | def GetMeas(_number, _name, _lan, _lon): | ||
| 60 | if _lan <= min_lan or _lan >= max_lan: | ||
| 61 | print("MeasUnit named {} have not current lan ({})".format(_name, _lan)) | ||
| 62 | return None | ||
| 63 | if _lon <= min_lon or _lon >= max_lon: | ||
| 64 | print("MeasUnit named {} have not current lon ({})".format(_name, _lon)) | ||
| 65 | return None | ||
| 66 | |||
| 67 | lan_delta = _lan - base_lan | ||
| 68 | lon_delta = _lon - base_lon | ||
| 69 | |||
| 70 | y_delta = lan_delta * lenght_lan | ||
| 71 | x_delta = lon_delta * lenght_lon | ||
| 72 | |||
| 73 | my = y_delta // base_pixel_len | ||
| 74 | mx = x_delta // base_pixel_len | ||
| 75 | |||
| 76 | result = dict(number = _number, name = _name, x = abs(mx), y = abs(my)) | ||
| 77 | return result | ||
| 78 | |||
| 79 | # Получить осадки по значению dbZ | ||
| 80 | def GetPrecByDBZ_2(_dbz): | ||
| 81 | result = 0 | ||
| 82 | |||
| 83 | if _dbz == 0 or _dbz > 127: | ||
| 84 | return result | ||
| 85 | |||
| 86 | step1 = (_dbz - 32) / 10 | ||
| 87 | step2 = 10 ** step1 | ||
| 88 | step3 = step2 / 200 | ||
| 89 | step4 = step3 ** 0.625 | ||
| 90 | result = step4 | ||
| 91 | return result | ||
| 92 | |||
| 93 | # Получаем все файлы из директории с сохранёнными изображениями | ||
| 94 | png_files = os.listdir(png_path) | ||
| 95 | print(png_files) | ||
| 96 | print("Lan border = {} - {}".format(min_lan, max_lan)) | ||
| 97 | print("Lon border = {} - {}".format(min_lon, max_lon)) | ||
| 98 | |||
| 99 | # Сформировать массив "матрица картинки-время" (время из названия файла) | ||
| 100 | store = [] | ||
| 101 | for png_f in png_files: | ||
| 102 | dt_value = png_f.replace('dj_286m_', '').replace('.png', '') | ||
| 103 | dt_value = int(dt_value) | ||
| 104 | dt_value = datetime.datetime.fromtimestamp(dt_value) | ||
| 105 | date_diff = datetime.timedelta(hours=0) | ||
| 106 | dt_value = dt_value + date_diff | ||
| 107 | file_data = imread(png_path + '\\' + png_f) | ||
| 108 | st_unit = dict( | ||
| 109 | datetime = dt_value, | ||
| 110 | matrix = file_data | ||
| 111 | ) | ||
| 112 | store.append(st_unit) | ||
| 113 | |||
| 114 | # Генерируем тестовые измерители | ||
| 115 | prec_meas = GenerateMeasurements() | ||
| 116 | |||
| 117 | # Болванка для шапки в Эксель | ||
| 118 | shapka = 'Date\t' | ||
| 119 | x_y = '' | ||
| 120 | |||
| 121 | # Формируем шапку для Экселя | ||
| 122 | for mes in prec_meas: | ||
| 123 | if mes is not None: | ||
| 124 | shapka += mes["name"] + str_limiter | ||
| 125 | x_y += "N={} X={} Y={}{}".format(mes["number"], mes["x"], mes["y"], str_limiter) | ||
| 126 | |||
| 127 | print(shapka) | ||
| 128 | |||
| 129 | # Формируем данные | ||
| 130 | main_data = "" | ||
| 131 | |||
| 132 | # Последниё интервал расчёта | ||
| 133 | last_datetime = store[0]["datetime"] | ||
| 134 | |||
| 135 | # Дельта (служебная) между интервалами расчёта | ||
| 136 | dt = datetime.timedelta(minutes=10) | ||
| 137 | |||
| 138 | # Пробегаемся по всем картинкам в хранилище | ||
| 139 | for prec_data in store: | ||
| 140 | |||
| 141 | # Формируем локальные переменные для цикла | ||
| 142 | lmatrix = prec_data["matrix"] | ||
| 143 | ldatetime = prec_data["datetime"] | ||
| 144 | date_diff = ldatetime - last_datetime | ||
| 145 | local_data = "" | ||
| 146 | |||
| 147 | # Фиксим (пустой строкой) промежутки между измерениями, если таковые имеются | ||
| 148 | while date_diff.seconds >= 1200: | ||
| 149 | local_data = "" | ||
| 150 | last_datetime = last_datetime + dt | ||
| 151 | local_data += last_datetime.__str__() + str_limiter | ||
| 152 | main_data += local_data + "\n" | ||
| 153 | date_diff = ldatetime - last_datetime | ||
| 154 | |||
| 155 | # Формируем для каждого измерителя оасдки в точке, согласно его прямоугольным координатам относительно картинки | ||
| 156 | local_data = "" | ||
| 157 | local_data += ldatetime.__str__() + str_limiter | ||
| 158 | for mes in prec_meas: | ||
| 159 | y = int(mes["y"]) | ||
| 160 | x = int(mes["x"]) | ||
| 161 | value = lmatrix[y][x][0] | ||
| 162 | prec = GetPrecByDBZ_2(value) | ||
| 163 | local_data += prec.__str__() + str_limiter | ||
| 164 | |||
| 165 | # Ищем максимум осадков на картинке | ||
| 166 | prec_max = 0 | ||
| 167 | ''' | ||
| 168 | for yy in lmatrix: | ||
| 169 | for xx in yy: | ||
| 170 | lm_value = xx[0] | ||
| 171 | m_prec = GetPrecByDBZ_2(lm_value) | ||
| 172 | if m_prec > prec_max: | ||
| 173 | prec_max = m_prec | ||
| 174 | |||
| 175 | local_data += prec_max.__str__() + str_limiter | ||
| 176 | ''' | ||
| 177 | # Вываливаем данные | ||
| 178 | main_data += local_data + "\n" | ||
| 179 | last_datetime = ldatetime | ||
| 180 | |||
| 181 | # Заменяем временные разделители и прочие символы для правильного отобраежния в Эксель | ||
| 182 | main_data = main_data.replace("||", "\t") | ||
| 183 | main_data = main_data.replace(".", ",") | ||
| 184 | |||
| 185 | # Пишем результат в текстовый файл | ||
| 186 | f = open('result.txt', 'w') | ||
| 187 | f.write(main_data) | ||
| 188 | f.close() | ||
| 189 | |||
| 190 | |||
| 191 | """ | ||
| 192 | 1. Для каждого измерителя ищем разницу в широте и долготе лот базовых координат | ||
| 193 | 1.1 Проверяем на выход за предельные значения | ||
| 194 | 2. По здначениям дельты и длинам градусов ищем разницу в метрах | ||
| 195 | 3. По разнице в метрах и базовому размеру пикселя ищем нужный квадрат как количество целых делений дельты в метрах на базовую длину градуса | ||
| 196 | """ | ||
| 197 |
| 1 | import sys | ||
| 2 | import os | ||
| 3 | import time | ||
| 4 | import datetime | ||
| 5 | import json | ||
| 6 | import jsonpickle | ||
| 7 | import importlib | ||
| 8 | import urllib.request | ||
| 9 | from imageio import imread | ||
| 10 | import redis | ||
| 11 | import requests | ||
| 12 | import dateutil.parser | ||
| 13 | |||
| 14 | time_result = None | ||
| 15 | |||
| 16 | try: | ||
| 17 | time_url = 'https://tilecache.rainviewer.com/api/maps.json' | ||
| 18 | time_result = json.load(urllib.request.urlopen(time_url)) | ||
| 19 | except Exception as e: | ||
| 20 | print("ERROR::{er}".format(er=e)) | ||
| 21 | exit() | ||
| 22 | |||
| 23 | if time_result is None or len(time_result) < 1: | ||
| 24 | print("time result is empty") | ||
| 25 | exit() | ||
| 26 | |||
| 27 | itime = time_result[0] | ||
| 28 | last_number = len(time_result) - 1 | ||
| 29 | |||
| 30 | last = 0 | ||
| 31 | for in_dt in time_result: | ||
| 32 | dt_value = datetime.datetime.fromtimestamp(in_dt) | ||
| 33 | print("{}-{}".format(in_dt, dt_value)) | ||
| 34 | print("DELTA = {}".format(in_dt - last)) | ||
| 35 | last = in_dt | ||
| 36 | |||
| 37 | dt_value = datetime.datetime.fromtimestamp(time_result[last_number]) | ||
| 38 | print("Текущий - {} -> {}".format(time_result[last_number], dt_value)) | ||
| 39 | |||
| 40 | |||
| 41 | # Определяем текущий тайм-слот | ||
| 42 | _datetime = datetime.datetime.now() | ||
| 43 | cur_min = (_datetime.minute // 10) * 10 | ||
| 44 | current_ts = datetime.datetime(_datetime.year, _datetime.month, _datetime.day, _datetime.hour, cur_min, 0, 0) | ||
| 45 | current_ts_ts = current_ts.timestamp() | ||
| 46 | last_ts = int(current_ts.timestamp()) + 600 | ||
| 47 | |||
| 48 | ''' | ||
| 49 | while datetime.datetime.now().timestamp() < last_ts: | ||
| 50 | |||
| 51 | time_result = None | ||
| 52 | time_url = 'https://tilecache.rainviewer.com/api/maps.json' | ||
| 53 | time_result = json.load(urllib.request.urlopen(time_url)) | ||
| 54 | |||
| 55 | if time_result is None or len(time_result) < 1 or current_ts_ts not in time_result: | ||
| 56 | print("{} No data...".format(datetime.datetime.now())) | ||
| 57 | time.sleep(30) | ||
| 58 | continue | ||
| 59 | |||
| 60 | png_data_url = 'https://tilecache.rainviewer.com/v2/radar/{time}/256/10/{lan}/{lon}/0/0_0.png'.format(time=itime, | ||
| 61 | lan="44.417242", | ||
| 62 | lon="38.72287") | ||
| 63 | |||
| 64 | img = imread(png_data_url) | ||
| 65 | ''' | ||
| 66 | |||
| 67 | url_ocm = r'http://10.110.0.37:8888/monitoring/rest/precipitation-measurements/33ce9a80-27df-41dd-8dbe-cf3ec918b4c2?time-from=2020-03-20 10:00:00&time-to=2020-03-20 16:00:00' | ||
| 68 | ocm_data = requests.get(url_ocm) | ||
| 69 | print(ocm_data.json()) | ||
| 70 | data = ocm_data.json() | ||
| 71 | |||
| 72 | for data_item in data: | ||
| 73 | print("value = time-{}, sum - {}".format(data_item["time"], data_item["sum"])) | ||
| 74 | #cur_cs = datetime.datetime.fromisoformat(data_item["time"]) | ||
| 75 | str = data_item["time"] | ||
| 76 | cur_cs = datetime.datetime.strptime(data_item["time"], '%Y-%m-%dT%H:%M:%SZ') | ||
| 77 | cs2 = dateutil.parser.parse(str, ignoretz=False) | ||
| 78 | |||
| 79 | cs3 = cs2.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None) | ||
| 80 | cs4 = dateutil.parser.parse(str, ignoretz=False).replace(tzinfo=datetime.timezone.utc).astimezone(tz=None) | ||
| 81 | |||
| 82 | #dateutil.parser.parse(data_item["time"]) | ||
| 83 | print(cur_cs) | ||
| 84 | print(cs2) | ||
| 85 | print(cs3) | ||
| 86 | print(cs4) | ||
| 87 |
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | |||
| 9 | |||
| 10 | |||
| 11 | png_path = r"d:\PYTHON\tests\test1\png" | ||
| 12 | png_result_path = r"d:\PYTHON\tests\test1\cutted" | ||
| 13 | |||
| 14 | lenght_lan = 79497.3714882 | ||
| 15 | lenght_lon = 111162.6 | ||
| 16 | base_pixel_len = 152.8740566 | ||
| 17 | str_limiter = '||' | ||
| 18 | |||
| 19 | d1plan_g = base_pixel_len / lenght_lan | ||
| 20 | d1plon_g = base_pixel_len / lenght_lon | ||
| 21 | x286lon = 38.72287 | ||
| 22 | x286lan = 44.417242 | ||
| 23 | |||
| 24 | base_lon = x286lon - (128 * d1plon_g) | ||
| 25 | min_lon = x286lon - (128 * d1plon_g) | ||
| 26 | max_lon = x286lon + (128 * d1plon_g) | ||
| 27 | |||
| 28 | base_lan = x286lan + (128 * d1plan_g) | ||
| 29 | min_lan = x286lan - (128 * d1plan_g) | ||
| 30 | max_lan = x286lan + (128 * d1plan_g) | ||
| 31 | |||
| 32 | # Генерировать измерители | ||
| 33 | def GenerateMeasurements(): | ||
| 34 | |||
| 35 | result = [] | ||
| 36 | l_dlan = d1plan_g * 48 | ||
| 37 | l_dlon = d1plon_g * 48 | ||
| 38 | ''' | ||
| 39 | result.append(GetMeas(1, 'X286|sp_dm', x286lan+l_dlan, x286lon-l_dlon)) | ||
| 40 | result.append(GetMeas(2, 'X286|sp_d0', x286lan+l_dlan, x286lon-0)) | ||
| 41 | result.append(GetMeas(3, 'X286|sp_dp', x286lan+l_dlan, x286lon+l_dlon)) | ||
| 42 | result.append(GetMeas(4, 'X286|s0_dm', x286lan+0, x286lon-l_dlon)) | ||
| 43 | result.append(GetMeas(5, 'X286|s0_d0', x286lan+0, x286lon-0)) | ||
| 44 | result.append(GetMeas(6, 'X286|s0_dp', x286lan+0, x286lon+l_dlon)) | ||
| 45 | result.append(GetMeas(7, 'X286|sm_dm', x286lan-l_dlan, x286lon-l_dlon)) | ||
| 46 | result.append(GetMeas(8, 'X286|sm_d0', x286lan-l_dlan, x286lon-0)) | ||
| 47 | result.append(GetMeas(9, 'X286|sm_dp', x286lan-l_dlan, x286lon+l_dlon)) | ||
| 48 | |||
| 49 | ''' | ||
| 50 | result.append(GetMeas(0, 'TEST_00', x286lan, x286lon)) | ||
| 51 | result.append(GetMeas(1, 'TEST_01', 44.3251277777778, 38.6788694444444)) | ||
| 52 | result.append(GetMeas(2, 'TEST_02', 44.3727555555556, 38.7005)) | ||
| 53 | result.append(GetMeas(3, 'TEST_03', 44.4186305555556, 38.6651361111111)) | ||
| 54 | result.append(GetMeas(4, 'TEST_04', 44.4545888888889, 38.6328638888889)) | ||
| 55 | result.append(GetMeas(5, 'TEST_05', 44.4508222222222, 38.6833333333333)) | ||
| 56 | result.append(GetMeas(6, 'TEST_06', 44.4329277777778, 38.7327722222222)) | ||
| 57 | result.append(GetMeas(7, 'TEST_07', 44.4106166666667, 38.7633277777778)) | ||
| 58 | result.append(GetMeas(8, 'TEST_08', 44.3846138888889, 38.7533722222222)) | ||
| 59 | result.append(GetMeas(9, 'TEST_09', 44.3416583333333, 38.735175)) | ||
| 60 | |||
| 61 | |||
| 62 | return result | ||
| 63 | |||
| 64 | # получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы | ||
| 65 | def GetMeas(_number, _name, _lan, _lon): | ||
| 66 | if _lan <= min_lan or _lan >= max_lan: | ||
| 67 | print("MeasUnit named {} have not current lan ({})".format(_name, _lan)) | ||
| 68 | return None | ||
| 69 | if _lon <= min_lon or _lon >= max_lon: | ||
| 70 | print("MeasUnit named {} have not current lon ({})".format(_name, _lon)) | ||
| 71 | return None | ||
| 72 | |||
| 73 | lan_delta = _lan - base_lan | ||
| 74 | lon_delta = _lon - base_lon | ||
| 75 | |||
| 76 | y_delta = lan_delta * lenght_lan | ||
| 77 | x_delta = lon_delta * lenght_lon | ||
| 78 | |||
| 79 | my = y_delta // base_pixel_len | ||
| 80 | mx = x_delta // base_pixel_len | ||
| 81 | |||
| 82 | result = dict(number = _number, name = _name, x = abs(mx), y = abs(my)) | ||
| 83 | return result | ||
| 84 | |||
| 85 | # Получить осадки по значению dbZ | ||
| 86 | def GetPrecByDBZ_2(_dbz): | ||
| 87 | result = 0 | ||
| 88 | |||
| 89 | if _dbz == 0 or _dbz > 127: | ||
| 90 | return result | ||
| 91 | |||
| 92 | step1 = (_dbz - 32) / 10 | ||
| 93 | step2 = 10 ** step1 | ||
| 94 | step3 = step2 / 200 | ||
| 95 | step4 = step3 ** 0.625 | ||
| 96 | result = step4 | ||
| 97 | return result | ||
| 98 | |||
| 99 | # Сгенерировать полигон по набору геокоординат | ||
| 100 | def GeneratePolygons(_meas_list, _number, _name): | ||
| 101 | # Максимальные значения координат Х и У для полигона | ||
| 102 | max_x = 0 | ||
| 103 | max_y = 0 | ||
| 104 | min_x = 256 | ||
| 105 | min_y = 256 | ||
| 106 | |||
| 107 | #Временный полигон | ||
| 108 | tmp_pol = [] | ||
| 109 | |||
| 110 | # Перебрать измерители последовательно и сформировать полигон как набор пар (х, у) плюс данные о границах полигона (прямоугольных) | ||
| 111 | for imeas in _meas_list: | ||
| 112 | mx =imeas["x"] | ||
| 113 | my = imeas["y"] | ||
| 114 | # Ищем прямоугольные границы полигона | ||
| 115 | if mx > max_x: | ||
| 116 | max_x = mx | ||
| 117 | if my > max_y: | ||
| 118 | max_y = my | ||
| 119 | if mx < min_x: | ||
| 120 | min_x = mx | ||
| 121 | if my < min_y: | ||
| 122 | min_y = my | ||
| 123 | tmp_pol.append((mx, my)) | ||
| 124 | |||
| 125 | 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) | ||
| 126 | result["pol"] = tmp_pol | ||
| 127 | return result | ||
| 128 | |||
| 129 | # Получить "обрезанную" матрицу по полигону | ||
| 130 | def GetCuttedMatrix(_image, _mpolygon): | ||
| 131 | matrix = _mpolygon["pol"] | ||
| 132 | max_x = int(_mpolygon["max_x"]) | ||
| 133 | max_y = int(_mpolygon["max_y"]) | ||
| 134 | min_x = int(_mpolygon["min_x"]) | ||
| 135 | min_y = int(_mpolygon["min_y"]) | ||
| 136 | mask = np.zeros(_image.shape, dtype=np.uint8) | ||
| 137 | roi_corners = np.array([matrix], dtype=np.int32) | ||
| 138 | channel_count = _image.shape[2] # i.e. 3 or 4 depending on your image | ||
| 139 | ignore_mask_color = (255,)*channel_count | ||
| 140 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 141 | masked_image = cv2.bitwise_and(_image, mask) | ||
| 142 | masked_image = masked_image[min_y:max_y, min_x:max_x] | ||
| 143 | return masked_image | ||
| 144 | |||
| 145 | |||
| 146 | # Получаем все файлы из директории с сохранёнными изображениями | ||
| 147 | png_files = os.listdir(png_path) | ||
| 148 | print(png_files) | ||
| 149 | print("Lan border = {} - {}".format(min_lan, max_lan)) | ||
| 150 | print("Lon border = {} - {}".format(min_lon, max_lon)) | ||
| 151 | |||
| 152 | # Сформировать массив "матрица картинки-время" (время из названия файла) | ||
| 153 | store = [] | ||
| 154 | for png_f in png_files: | ||
| 155 | dt_value = png_f.replace('dj_286m_', '').replace('.png', '') | ||
| 156 | dt_value = int(dt_value) | ||
| 157 | dt_value = datetime.datetime.fromtimestamp(dt_value) | ||
| 158 | date_diff = datetime.timedelta(hours=2) | ||
| 159 | dt_value = dt_value + date_diff | ||
| 160 | file_data = imread(png_path + '\\' + png_f) | ||
| 161 | st_unit = dict( | ||
| 162 | datetime = dt_value, | ||
| 163 | matrix = file_data | ||
| 164 | ) | ||
| 165 | store.append(st_unit) | ||
| 166 | |||
| 167 | # Генерируем тестовые измерители | ||
| 168 | prec_meas = GenerateMeasurements() | ||
| 169 | |||
| 170 | # Формируем данные | ||
| 171 | main_data = "" | ||
| 172 | |||
| 173 | ################################################################ | ||
| 174 | # TEST - генерация обрезанных файлов | ||
| 175 | |||
| 176 | main_pol = GeneratePolygons([prec_meas[0], prec_meas[3], prec_meas[4], prec_meas[5], prec_meas[6]], 1, "Verh") | ||
| 177 | main_pol = GeneratePolygons([prec_meas[0], prec_meas[6], prec_meas[7], prec_meas[8], prec_meas[9], prec_meas[1], prec_meas[2]], 2, "Nige_Polkovnichego") | ||
| 178 | pol_store = [] | ||
| 179 | pol_store.append(main_pol) | ||
| 180 | cutted_store = [] | ||
| 181 | |||
| 182 | ''' | ||
| 183 | for m_image in store: | ||
| 184 | image = m_image["matrix"] | ||
| 185 | masked_image = GetCuttedMatrix(image, main_pol) | ||
| 186 | path_to_save = "d:\\PYTHON\\tests\\test1\\cutted\\{name}_{dt}.png".format(name = main_pol["name"], dt = m_image["datetime"].timestamp()) | ||
| 187 | #cv2.imwrite(path_to_save, masked_image) | ||
| 188 | cutted_store.append(masked_image) | ||
| 189 | ''' | ||
| 190 | ################################################################ | ||
| 191 | |||
| 192 | # Последниё интервал расчёта | ||
| 193 | last_datetime = store[0]["datetime"] | ||
| 194 | |||
| 195 | # Дельта (служебная) между интервалами расчёта | ||
| 196 | dt = datetime.timedelta(minutes=10) | ||
| 197 | |||
| 198 | # Пробегаемся по всем картинкам в хранилище | ||
| 199 | for prec_data in store: | ||
| 200 | |||
| 201 | # Формируем локальные переменные для цикла | ||
| 202 | lmatrix = prec_data["matrix"] | ||
| 203 | ldatetime = prec_data["datetime"] | ||
| 204 | date_diff = ldatetime - last_datetime | ||
| 205 | local_data = "" | ||
| 206 | |||
| 207 | # Фиксим (пустой строкой) промежутки между измерениями, если таковые имеются | ||
| 208 | while date_diff.seconds >= 1200: | ||
| 209 | local_data = "" | ||
| 210 | last_datetime = last_datetime + dt | ||
| 211 | local_data += last_datetime.__str__() + str_limiter | ||
| 212 | main_data += local_data + "\n" | ||
| 213 | date_diff = ldatetime - last_datetime | ||
| 214 | |||
| 215 | # Формируем для каждого полигона осадки, согласно его прямоугольным координатам относительно картинки | ||
| 216 | local_data = "" | ||
| 217 | local_data += ldatetime.__str__() + str_limiter | ||
| 218 | for pol in pol_store: | ||
| 219 | masked_image = GetCuttedMatrix(lmatrix, pol) | ||
| 220 | sum_prec = 0 | ||
| 221 | for yy in masked_image: | ||
| 222 | for xx in yy: | ||
| 223 | lm_value = xx[0] | ||
| 224 | m_prec = GetPrecByDBZ_2(lm_value) | ||
| 225 | sum_prec += m_prec | ||
| 226 | local_data += sum_prec.__str__() + str_limiter | ||
| 227 | # Вываливаем данные | ||
| 228 | main_data += local_data + "\n" | ||
| 229 | last_datetime = ldatetime | ||
| 230 | |||
| 231 | # Заменяем временные разделители и прочие символы для правильного отобраежния в Эксель | ||
| 232 | main_data = main_data.replace("||", "\t") | ||
| 233 | main_data = main_data.replace(".", ",") | ||
| 234 | |||
| 235 | # Пишем результат в текстовый файл | ||
| 236 | f = open('result.txt', 'w') | ||
| 237 | f.write(main_data) | ||
| 238 | f.close() | ||
| 239 | |||
| 240 | |||
| 241 | """ | ||
| 242 | 1. Для каждого измерителя ищем разницу в широте и долготе лот базовых координат | ||
| 243 | 1.1 Проверяем на выход за предельные значения | ||
| 244 | 2. По здначениям дельты и длинам градусов ищем разницу в метрах | ||
| 245 | 3. По разнице в метрах и базовому размеру пикселя ищем нужный квадрат как количество целых делений дельты в метрах на базовую длину градуса | ||
| 246 | """ | ||
| 247 |
650 Bytes
943 Bytes
| 1 | import urllib.request | ||
| 2 | import json | ||
| 3 | import os | ||
| 4 | import datetime | ||
| 5 | from imageio import imread | ||
| 6 | import cv2 | ||
| 7 | import numpy as np | ||
| 8 | import loca_data | ||
| 9 | import duamel_model | ||
| 10 | import matplotlib.pyplot as plt | ||
| 11 | import sher_duam_class | ||
| 12 | |||
| 13 | |||
| 14 | png_path = r"d:\PYTHON\tests\test1\png" | ||
| 15 | |||
| 16 | lenght_lan = 79497.3714882 | ||
| 17 | lenght_lon = 111162.6 | ||
| 18 | base_pixel_len = 152.8740566 | ||
| 19 | str_limiter = '||' | ||
| 20 | |||
| 21 | d1plan_g = base_pixel_len / lenght_lan | ||
| 22 | d1plon_g = base_pixel_len / lenght_lon | ||
| 23 | x286lon = 38.72287 | ||
| 24 | x286lan = 44.417242 | ||
| 25 | |||
| 26 | base_lon = x286lon - (128 * d1plon_g) | ||
| 27 | min_lon = x286lon - (128 * d1plon_g) | ||
| 28 | max_lon = x286lon + (128 * d1plon_g) | ||
| 29 | |||
| 30 | base_lan = x286lan + (128 * d1plan_g) | ||
| 31 | min_lan = x286lan - (128 * d1plan_g) | ||
| 32 | max_lan = x286lan + (128 * d1plan_g) | ||
| 33 | |||
| 34 | pol_store = [] | ||
| 35 | prec_meas = [] | ||
| 36 | |||
| 37 | ''' | ||
| 38 | 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) | ||
| 39 | 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) | ||
| 40 | flow_rate = duamel_model.CatchmentArea(_capacity=22.2, _in_filter=1.0, _out_filter=0.09) | ||
| 41 | flow_rate1 = duamel_model.CatchmentArea(_capacity=100.0, _in_filter=2.0, _out_filter=0.09) | ||
| 42 | 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) | ||
| 43 | 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) | ||
| 44 | ''' | ||
| 45 | duamel = duamel_model.DumlRiverModel(_k_n = 1.0, _k_korr = 15.0, _res_add_val = 20.0, _dmi_up_per = 0.1, _dmi_down_per = 40.0) | ||
| 46 | duamel1 = duamel_model.DumlRiverModel() | ||
| 47 | flow_rate = duamel_model.CatchmentArea(_capacity = 50, _in_filter = 5.0, _out_filter = 0.045) | ||
| 48 | flow_rate1 = duamel_model.CatchmentArea() | ||
| 49 | level_calc = duamel_model.RiverCrossSection() | ||
| 50 | level_calc1 = duamel_model.RiverCrossSection() | ||
| 51 | sher_duam = sher_duam_class.TestSherDuamel() | ||
| 52 | sher_duam1 = sher_duam_class.TestSherDuamel() | ||
| 53 | |||
| 54 | # Генерировать измерители всех типов | ||
| 55 | def GenerateMeasurements(): | ||
| 56 | |||
| 57 | # Точки для полигонов | ||
| 58 | result = [] | ||
| 59 | all_result = [] | ||
| 60 | |||
| 61 | # Получение координат полигона водосбора Джубги | ||
| 62 | pcs = loca_data.GetGeoCoordPolygon() | ||
| 63 | |||
| 64 | # Последняя запись - для отбрасывания дублей пикселей | ||
| 65 | p_last = dict(x = -1.0, y = 0.0) | ||
| 66 | |||
| 67 | # Получаем список точек полигона | ||
| 68 | for pc in pcs: | ||
| 69 | p = GetMeas(pc[0], pc[1], pc[2], pc[3]) | ||
| 70 | |||
| 71 | if p_last['x'] == -1.0: | ||
| 72 | p_last['x'] = p['x'] | ||
| 73 | p_last['y'] = p['y'] | ||
| 74 | all_result.append(p) | ||
| 75 | else: | ||
| 76 | if p_last['x'] != p['x'] and p_last['y'] != p['y']: | ||
| 77 | all_result.append(p) | ||
| 78 | |||
| 79 | p_last['x'] = p['x'] | ||
| 80 | p_last['y'] = p['y'] | ||
| 81 | |||
| 82 | result.append(GetMeas(0, 'TEST_00', x286lan, x286lon)) | ||
| 83 | result.append(GetMeas(1, 'TEST_01', 44.3251277777778, 38.6788694444444)) | ||
| 84 | result.append(GetMeas(2, 'TEST_02', 44.3727555555556, 38.7005)) | ||
| 85 | result.append(GetMeas(3, 'TEST_03', 44.4186305555556, 38.6651361111111)) | ||
| 86 | result.append(GetMeas(4, 'TEST_04', 44.4545888888889, 38.6328638888889)) | ||
| 87 | result.append(GetMeas(5, 'TEST_05', 44.4508222222222, 38.6833333333333)) | ||
| 88 | result.append(GetMeas(6, 'TEST_06', 44.4329277777778, 38.7327722222222)) | ||
| 89 | result.append(GetMeas(7, 'TEST_07', 44.4106166666667, 38.7633277777778)) | ||
| 90 | result.append(GetMeas(8, 'TEST_08', 44.3846138888889, 38.7533722222222)) | ||
| 91 | result.append(GetMeas(9, 'TEST_09', 44.3416583333333, 38.735175)) | ||
| 92 | |||
| 93 | prec_meas.append(GetMeas(5, 'X286|s0_d0', x286lan+0, x286lon-0)) | ||
| 94 | |||
| 95 | pol_store.append(GeneratePolygons(all_result, 0, "All")) | ||
| 96 | #pol_store.append(GeneratePolygons([result[0], result[3], result[4], result[5], result[6]], 1, "Verh")) | ||
| 97 | #pol_store.append(GeneratePolygons([result[0], result[6], result[7], result[8], result[9], result[1], result[2]], 2, "Nige_Polkovnichego")) | ||
| 98 | |||
| 99 | return | ||
| 100 | |||
| 101 | # получить измеритель (имя, номер, х-коорд картинки и у-коорд картинки) из широты и долготы | ||
| 102 | def GetMeas(_number, _name, _lan, _lon): | ||
| 103 | if _lan <= min_lan or _lan >= max_lan: | ||
| 104 | print("MeasUnit named {} have not current lan ({})".format(_name, _lan)) | ||
| 105 | return None | ||
| 106 | if _lon <= min_lon or _lon >= max_lon: | ||
| 107 | print("MeasUnit named {} have not current lon ({})".format(_name, _lon)) | ||
| 108 | return None | ||
| 109 | |||
| 110 | lan_delta = _lan - base_lan | ||
| 111 | lon_delta = _lon - base_lon | ||
| 112 | |||
| 113 | y_delta = lan_delta * lenght_lan | ||
| 114 | x_delta = lon_delta * lenght_lon | ||
| 115 | |||
| 116 | my = y_delta // base_pixel_len | ||
| 117 | mx = x_delta // base_pixel_len | ||
| 118 | |||
| 119 | result = dict(number = _number, name = _name, x = abs(mx), y = abs(my)) | ||
| 120 | return result | ||
| 121 | |||
| 122 | # Получить осадки по значению dbZ | ||
| 123 | def GetPrecByDBZ_2(_dbz): | ||
| 124 | result = 0 | ||
| 125 | |||
| 126 | if _dbz == 0 or _dbz > 127: | ||
| 127 | return result | ||
| 128 | |||
| 129 | step1 = (_dbz - 32) / 10 | ||
| 130 | step2 = 10 ** step1 | ||
| 131 | step3 = step2 / 200 | ||
| 132 | step4 = step3 ** 0.625 | ||
| 133 | result = step4 | ||
| 134 | return result | ||
| 135 | |||
| 136 | # Сгенерировать полигон по набору геокоординат | ||
| 137 | def GeneratePolygons(_meas_list, _number, _name): | ||
| 138 | # Максимальные значения координат Х и У для полигона | ||
| 139 | max_x = 0 | ||
| 140 | max_y = 0 | ||
| 141 | min_x = 256 | ||
| 142 | min_y = 256 | ||
| 143 | |||
| 144 | #Временный полигон | ||
| 145 | tmp_pol = [] | ||
| 146 | |||
| 147 | # Перебрать измерители последовательно и сформировать полигон как набор пар (х, у) плюс данные о границах полигона (прямоугольных) | ||
| 148 | for imeas in _meas_list: | ||
| 149 | mx =imeas["x"] | ||
| 150 | my = imeas["y"] | ||
| 151 | # Ищем прямоугольные границы полигона | ||
| 152 | if mx > max_x: | ||
| 153 | max_x = mx | ||
| 154 | if my > max_y: | ||
| 155 | max_y = my | ||
| 156 | if mx < min_x: | ||
| 157 | min_x = mx | ||
| 158 | if my < min_y: | ||
| 159 | min_y = my | ||
| 160 | tmp_pol.append((mx, my)) | ||
| 161 | |||
| 162 | 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) | ||
| 163 | result["pol"] = tmp_pol | ||
| 164 | return result | ||
| 165 | |||
| 166 | # Получить "обрезанную" матрицу по полигону | ||
| 167 | def GetCuttedMatrix(_image, _mpolygon): | ||
| 168 | |||
| 169 | matrix = _mpolygon["pol"] | ||
| 170 | |||
| 171 | max_x = int(_mpolygon["max_x"]) | ||
| 172 | max_y = int(_mpolygon["max_y"]) | ||
| 173 | min_x = int(_mpolygon["min_x"]) | ||
| 174 | min_y = int(_mpolygon["min_y"]) | ||
| 175 | |||
| 176 | mask = np.zeros(_image.shape, dtype=np.uint8) | ||
| 177 | roi_corners = np.array([matrix], dtype=np.int32) | ||
| 178 | channel_count = _image.shape[2] # i.e. 3 or 4 depending on your image | ||
| 179 | ignore_mask_color = (255,)*channel_count | ||
| 180 | cv2.fillPoly(mask, roi_corners, ignore_mask_color) | ||
| 181 | masked_image = cv2.bitwise_and(_image, mask) | ||
| 182 | masked_image = masked_image[min_y:max_y, min_x:max_x] | ||
| 183 | |||
| 184 | return masked_image | ||
| 185 | |||
| 186 | |||
| 187 | # Получаем все файлы из директории с сохранёнными изображениями | ||
| 188 | png_files = os.listdir(png_path) | ||
| 189 | print(png_files) | ||
| 190 | print("Lan border = {} - {}".format(min_lan, max_lan)) | ||
| 191 | print("Lon border = {} - {}".format(min_lon, max_lon)) | ||
| 192 | |||
| 193 | # Сформировать массив "матрица картинки-время" (время из названия файла) | ||
| 194 | store = [] | ||
| 195 | for png_f in png_files: | ||
| 196 | dt_value = png_f.replace('dj_286m_', '').replace('.png', '') | ||
| 197 | dt_value = int(dt_value) | ||
| 198 | dt_value = datetime.datetime.fromtimestamp(dt_value) | ||
| 199 | date_diff = datetime.timedelta(hours=0) | ||
| 200 | dt_value = dt_value + date_diff | ||
| 201 | file_data = imread(png_path + '\\' + png_f) | ||
| 202 | st_unit = dict( | ||
| 203 | datetime = dt_value, | ||
| 204 | matrix = file_data | ||
| 205 | ) | ||
| 206 | store.append(st_unit) | ||
| 207 | |||
| 208 | # Генерируем измерители | ||
| 209 | GenerateMeasurements() | ||
| 210 | |||
| 211 | # Формируем данные | ||
| 212 | main_data = "Дата||АГК-286М||АГК-34||РАД-286М||RAD286(cor)||Сумма ВСЕГО||Сумма ВСЕГО(кор)||Сумма ВСЕГО ОБ||Сумма ВСЕГО ОБ(кор)||Flow||Duamel||DuamLevel||\n" | ||
| 213 | |||
| 214 | # Последниё интервал расчёта | ||
| 215 | last_datetime = store[0]["datetime"] | ||
| 216 | |||
| 217 | # Дельта (служебная) между интервалами расчёта | ||
| 218 | dt = datetime.timedelta(minutes=10) | ||
| 219 | |||
| 220 | # Интервал времени | ||
| 221 | datetime_min = datetime.datetime(2020, 1, 29, 22, 50, 0) | ||
| 222 | datetime_max = datetime.datetime(2020, 2, 4, 15, 40, 0) | ||
| 223 | |||
| 224 | # Реальные 286М и 34 | ||
| 225 | real286 = loca_data.GetPrec286M() | ||
| 226 | real34 = loca_data.GetLevel34() | ||
| 227 | |||
| 228 | dtcounter = -1 | ||
| 229 | |||
| 230 | # Для графиков | ||
| 231 | mas_x = [] #time | ||
| 232 | mas_real = [] #real water level | ||
| 233 | |||
| 234 | |||
| 235 | mas_prec = [] #real prec | ||
| 236 | |||
| 237 | mas_vol = [] #calc water volume | ||
| 238 | mas_vol1 = [] #calc water volume (corr) | ||
| 239 | |||
| 240 | mas_vol_k = [] #calc volume with reserv k | ||
| 241 | mas_vol1_k = [] #calc volume with reserv k (corr) | ||
| 242 | |||
| 243 | |||
| 244 | mas_duam = [] #duamel water level | ||
| 245 | mas_duam1 = [] #duamel water level (корр) | ||
| 246 | mas_sher_duam = [] #дюамель от шержукова | ||
| 247 | mas_sher_duam1 = [] #дюамель от шержукова (корр) | ||
| 248 | mas_wvol = [] #water volume | ||
| 249 | |||
| 250 | reserv_volume_koef = 1.0 | ||
| 251 | reserv_volume_koef_corr = 1.0 | ||
| 252 | |||
| 253 | # Пробегаемся по всем датам в хранилище реальных осадков | ||
| 254 | for rdata_key in real286.keys(): | ||
| 255 | |||
| 256 | dtcounter = dtcounter + 1 | ||
| 257 | mas_x.append(dtcounter) | ||
| 258 | |||
| 259 | koef_multy_re_d_rad = 1 | ||
| 260 | koef_addit_re_m_rad = 0 | ||
| 261 | prec_data = None | ||
| 262 | lmatrix = None | ||
| 263 | ldatetime = rdata_key | ||
| 264 | print("{}\t{}\t{}".format(ldatetime, reserv_volume_koef, reserv_volume_koef_corr)) | ||
| 265 | local_data = "" | ||
| 266 | local_data += ldatetime.__str__() + str_limiter | ||
| 267 | |||
| 268 | # 0. Осадки реальные | ||
| 269 | real_prec = real286[rdata_key] | ||
| 270 | local_data += real_prec.__str__() + str_limiter | ||
| 271 | |||
| 272 | # 0.1 Уровень реальный | ||
| 273 | real_level = real34[rdata_key] | ||
| 274 | local_data += real_level.__str__() + str_limiter | ||
| 275 | mas_real.append(real_level) | ||
| 276 | |||
| 277 | for imgmatrix in store: | ||
| 278 | if imgmatrix["datetime"] == rdata_key: | ||
| 279 | lmatrix = imgmatrix["matrix"] | ||
| 280 | |||
| 281 | if lmatrix is None: | ||
| 282 | local_data += "0||0||0||0||" | ||
| 283 | rain_corr = real_prec | ||
| 284 | |||
| 285 | vol_water = real_prec * reserv_volume_koef | ||
| 286 | vol_water_corr = real_prec * reserv_volume_koef_corr | ||
| 287 | |||
| 288 | mas_vol.append(0.0) | ||
| 289 | mas_vol1.append(0.0) | ||
| 290 | |||
| 291 | mas_vol_k.append(vol_water) | ||
| 292 | mas_vol1_k.append(vol_water_corr) | ||
| 293 | |||
| 294 | rain = vol_water * 0.0000099471691 * 8 | ||
| 295 | rain_corr = vol_water_corr * 0.0000099471691 * 8 | ||
| 296 | |||
| 297 | flow = flow_rate.calc_surface_flow(rain_corr) | ||
| 298 | flow1 = flow_rate1.calc_surface_flow(rain_corr) | ||
| 299 | |||
| 300 | duam_value = duamel.model_step(dtcounter, flow) | ||
| 301 | duam_value1 = duamel1.model_step(dtcounter, flow1) | ||
| 302 | |||
| 303 | wlevel = level_calc.bs_water_level(duam_value) | ||
| 304 | wlevel1 = level_calc.bs_water_level(duam_value1) | ||
| 305 | |||
| 306 | mas_duam.append(wlevel) | ||
| 307 | mas_duam1.append(wlevel1) | ||
| 308 | |||
| 309 | test_sher_level = sher_duam.CalculateLevel(flow, dtcounter) | ||
| 310 | test_sher_level1 = sher_duam.CalculateLevel(flow1, dtcounter) | ||
| 311 | |||
| 312 | mas_sher_duam.append(test_sher_level) | ||
| 313 | mas_sher_duam1.append(test_sher_level1) | ||
| 314 | |||
| 315 | mas_wvol.append(0.0) | ||
| 316 | |||
| 317 | local_data += flow.__str__() + str_limiter | ||
| 318 | local_data += duam_value.__str__() + str_limiter | ||
| 319 | local_data += duam_value.__str__() + str_limiter | ||
| 320 | local_data += wlevel.__str__() + str_limiter | ||
| 321 | |||
| 322 | main_data += local_data + "\n" | ||
| 323 | continue | ||
| 324 | |||
| 325 | # 1. Расчёт осадков по координатам | ||
| 326 | # Формируем для каждого измерителя оасдки в точке, согласно его прямоугольным координатам относительно картинки | ||
| 327 | mes = prec_meas[0] | ||
| 328 | y = int(mes["y"]) | ||
| 329 | x = int(mes["x"]) | ||
| 330 | value = lmatrix[y][x][0] | ||
| 331 | dmrl_prec = GetPrecByDBZ_2(value) | ||
| 332 | dmrl_prec = dmrl_prec / 6 | ||
| 333 | local_data += dmrl_prec.__str__() + str_limiter | ||
| 334 | |||
| 335 | # 1.1 Считаем коэффициенты | ||
| 336 | if dmrl_prec > 0 and real_prec > 0: | ||
| 337 | koef_multy_re_d_rad = real_prec / dmrl_prec | ||
| 338 | koef_addit_re_m_rad = 0 | ||
| 339 | elif dmrl_prec == 0 and real_prec > 0: | ||
| 340 | koef_multy_re_d_rad = 1 | ||
| 341 | koef_addit_re_m_rad = real_prec - dmrl_prec | ||
| 342 | elif dmrl_prec > 0 and real_prec == 0: | ||
| 343 | koef_multy_re_d_rad = 1 | ||
| 344 | koef_addit_re_m_rad = 0 | ||
| 345 | |||
| 346 | # 1.2 Считаем осадки после корректировки | ||
| 347 | dmrl_prec_cor = (dmrl_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad | ||
| 348 | local_data += dmrl_prec_cor.__str__() + str_limiter | ||
| 349 | |||
| 350 | # 2. Расчет площадей и осадков на площадях | ||
| 351 | |||
| 352 | for pol in pol_store: | ||
| 353 | masked_image = GetCuttedMatrix(lmatrix, pol) | ||
| 354 | sum_prec = 0 | ||
| 355 | sum_squere = 0 | ||
| 356 | sum_prec_cor = 0 | ||
| 357 | vol_water = 0 | ||
| 358 | vol_water_cor = 0 | ||
| 359 | for yy in masked_image: | ||
| 360 | for xx in yy: | ||
| 361 | lm_value = xx[0] | ||
| 362 | m_prec = GetPrecByDBZ_2(lm_value) | ||
| 363 | m_prec = m_prec / 6 | ||
| 364 | |||
| 365 | if m_prec > 0: | ||
| 366 | sum_squere += 1 | ||
| 367 | |||
| 368 | sum_prec += m_prec | ||
| 369 | |||
| 370 | m_prec_cor = ((m_prec * koef_multy_re_d_rad) + koef_addit_re_m_rad) | ||
| 371 | sum_prec_cor = sum_prec_cor + m_prec_cor | ||
| 372 | |||
| 373 | vol_local = base_pixel_len * base_pixel_len * 1/1000 * m_prec | ||
| 374 | vol_water += vol_local | ||
| 375 | |||
| 376 | vol_local_cor = base_pixel_len * base_pixel_len * 1/1000 * m_prec_cor | ||
| 377 | vol_water_cor += vol_local_cor | ||
| 378 | |||
| 379 | |||
| 380 | mas_vol.append(vol_water) | ||
| 381 | mas_vol1.append(vol_water_cor) | ||
| 382 | |||
| 383 | mas_vol_k.append(vol_water) | ||
| 384 | mas_vol1_k.append(vol_water_cor) | ||
| 385 | |||
| 386 | #расчет резервных коэффициентов | ||
| 387 | tmp_reserv_volume_koef = 0 | ||
| 388 | tmp_reserv_volume_koef_corr = 0 | ||
| 389 | |||
| 390 | if real_prec != 0: | ||
| 391 | tmp_reserv_volume_koef = vol_water / real_prec | ||
| 392 | tmp_reserv_volume_koef_corr = vol_water_cor / real_prec | ||
| 393 | date_diff = rdata_key - datetime_min | ||
| 394 | |||
| 395 | if date_diff.seconds == 0: | ||
| 396 | reserv_volume_koef = tmp_reserv_volume_koef | ||
| 397 | reserv_volume_koef_corr = tmp_reserv_volume_koef_corr | ||
| 398 | else: | ||
| 399 | per_num = date_diff.seconds / 600 | ||
| 400 | tmp_mult = ((reserv_volume_koef * per_num) + tmp_reserv_volume_koef) / (per_num + 1) | ||
| 401 | tmp_mult_corr = ((reserv_volume_koef * per_num) + reserv_volume_koef_corr) / (per_num + 1) | ||
| 402 | reserv_volume_koef = tmp_mult | ||
| 403 | reserv_volume_koef_corr = tmp_mult_corr | ||
| 404 | |||
| 405 | |||
| 406 | local_data += sum_prec.__str__() + str_limiter | ||
| 407 | local_data += sum_prec_cor.__str__() + str_limiter | ||
| 408 | local_data += vol_water.__str__() + str_limiter | ||
| 409 | local_data += vol_water_cor.__str__() + str_limiter | ||
| 410 | |||
| 411 | rain = vol_water * 0.0000099471691 * 8 | ||
| 412 | rain_corr = vol_water_cor * 0.0000099471691 * 8 | ||
| 413 | |||
| 414 | mas_wvol.append(rain_corr) | ||
| 415 | |||
| 416 | flow = flow_rate.calc_surface_flow(rain) | ||
| 417 | flow1 = flow_rate1.calc_surface_flow(rain_corr) | ||
| 418 | |||
| 419 | duam_value = duamel.model_step(dtcounter, flow) | ||
| 420 | duam_valk1 = duamel1.model_step(dtcounter, flow1) | ||
| 421 | |||
| 422 | wlevel = level_calc.bs_water_level(duam_value) | ||
| 423 | wlevel1 = level_calc.bs_water_level(duam_valk1) | ||
| 424 | |||
| 425 | test_sher_level = sher_duam.CalculateLevel(flow, dtcounter) | ||
| 426 | test_sher_level1 = sher_duam.CalculateLevel(flow1, dtcounter) | ||
| 427 | |||
| 428 | mas_duam.append(wlevel) | ||
| 429 | mas_duam1.append(wlevel1) | ||
| 430 | mas_sher_duam.append(test_sher_level) | ||
| 431 | mas_sher_duam1.append(test_sher_level1) | ||
| 432 | |||
| 433 | local_data += flow.__str__() + str_limiter | ||
| 434 | local_data += duam_value.__str__() + str_limiter | ||
| 435 | local_data += wlevel.__str__() + str_limiter | ||
| 436 | local_data += wlevel1.__str__() + str_limiter | ||
| 437 | |||
| 438 | # Вываливаем данные | ||
| 439 | main_data += local_data + "\n" | ||
| 440 | |||
| 441 | # Заменяем временные разделители и прочие символы для правильного отобраежния в Эксель | ||
| 442 | main_data = main_data.replace("||", "\t") | ||
| 443 | |||
| 444 | # Пишем результат в текстовый файл | ||
| 445 | f = open('result.txt', 'w') | ||
| 446 | f.write(main_data) | ||
| 447 | f.close() | ||
| 448 | |||
| 449 | fig, ax = plt.subplots() | ||
| 450 | |||
| 451 | #ax.plot(mas_x, mas_real, label = 'AGK-34') | ||
| 452 | ax.plot(mas_x, mas_vol, label = 'VOL') | ||
| 453 | ax.plot(mas_x, mas_vol1, label = 'VOL_C') | ||
| 454 | ax.plot(mas_x, mas_vol, label = 'VOL_K') | ||
| 455 | ax.plot(mas_x, mas_vol, label = 'VOL_C_K') | ||
| 456 | #ax.plot(mas_x, mas_duam, label = 'DUAM') | ||
| 457 | #ax.plot(mas_x, mas_duam1, label = 'DUAM_corr') | ||
| 458 | #ax.plot(mas_x, mas_sher_duam, label = 'SHER_DUAM') | ||
| 459 | #ax.plot(mas_x, mas_sher_duam1, label = 'SHER_DUAM_corr') | ||
| 460 | |||
| 461 | ax.legend() | ||
| 462 | |||
| 463 | plt.show() | ||
| 464 | |||
| 465 | |||
| 466 | |||
| 467 | """ | ||
| 468 | 1. Для каждого измерителя ищем разницу в широте и долготе лот базовых координат | ||
| 469 | 1.1 Проверяем на выход за предельные значения | ||
| 470 | 2. По здначениям дельты и длинам градусов ищем разницу в метрах | ||
| 471 | 3. По разнице в метрах и базовому размеру пикселя ищем нужный квадрат как количество целых делений дельты в метрах на базовую длину градуса | ||
| 472 | """ | ||
| 473 |
| 1 | Проект "Треугольные осадки" | ||
| 2 | I ЭТАП - ОТРАБОТКА ОБЩЕГО МАТЕМАТИЧСКОГО РЕШЕНИЯ | ||
| 3 | . Задать три точки с координатами Р1, Р2, Р3 - (х1у1с1, х2у2с2, х3у3с3) | ||
| 4 | . Определить "площадь решения" в виде плоского рисунка | ||
| 5 | . Нарисовать треугольник Т по трём точкам Рх | ||
| 6 | . Определить формулу плоскости ПЛ по трем точкам Рх | ||
| 7 | . Определить формулу принадлежности произвольной точки Рн треугольнику Р1Р2Р3 | ||
| 8 | . Пройтись по каждой точке Рпр площади решения и определить, принадлежит ли выбранная точка треугольнику Т | ||
| 9 | . Если принадлежит - то определить цвет по формуле ПЛ и установить его на площади решения | ||
| 10 | . Сохранить результат в виде рисунка png |
| 1 | import numpy as np | ||
| 2 | import matplotlib.pyplot as plt | ||
| 3 | import datetime | ||
| 4 | import os.path | ||
| 5 | import loca_data | ||
| 6 | import math | ||
| 7 | |||
| 8 | ''' | ||
| 9 | # реализация метода ньютона-рафсона | ||
| 10 | def newton_raphson(study_func, target_val, start_x, max_iter_count=10, max_err=1e-3, delta_x=1e-6): | ||
| 11 | |||
| 12 | # начальное значение аргумента | ||
| 13 | finded_x = start_x | ||
| 14 | |||
| 15 | # Цикл нахождения решения | ||
| 16 | iter_count = 0 | ||
| 17 | err_y = 1e20 | ||
| 18 | |||
| 19 | # цикл поиска решения | ||
| 20 | while (iter_count <= max_iter_count) and (abs(err_y) > max_err): | ||
| 21 | |||
| 22 | # Вычисляем производную dy/dx в точке x | ||
| 23 | # dfdx в принципе нам может быть известен аналитически, и в таком случае | ||
| 24 | # предпочтительно использовать аналитическое выражение. | ||
| 25 | dfdx = (study_func(finded_x + 0.5 * delta_x) - study_func(finded_x - 0.5 * delta_x)) / delta_x | ||
| 26 | |||
| 27 | # Находим приращение по y | ||
| 28 | err_y = study_func(finded_x) - target_val | ||
| 29 | # и по x | ||
| 30 | err_x = err_y / dfdx | ||
| 31 | # Получаем новое решение | ||
| 32 | finded_x = finded_x - err_x | ||
| 33 | |||
| 34 | # меняем к - во итераций | ||
| 35 | iter_count += 1 | ||
| 36 | |||
| 37 | return finded_x | ||
| 38 | ''' | ||
| 39 | ''' | ||
| 40 | x = np.random.randint(low=1, high=11, size=50) | ||
| 41 | y = x + np.random.randint(1, 5, size=x.size) | ||
| 42 | data = np.column_stack((x, y)) | ||
| 43 | |||
| 44 | fig, (ax1, ax2) = plt.subplots( | ||
| 45 | nrows=1, ncols=2, | ||
| 46 | figsize=(8, 4) | ||
| 47 | ) | ||
| 48 | |||
| 49 | ax1.scatter(x=x, y=y, marker='o', c='r', edgecolor='b') | ||
| 50 | ax1.set_title('Scatter: $x$ versus $y$') | ||
| 51 | ax1.set_xlabel('$x$') | ||
| 52 | ax1.set_ylabel('$y$') | ||
| 53 | |||
| 54 | ax2.hist( | ||
| 55 | data, bins=np.arange(data.min(), data.max()), | ||
| 56 | label=('x', 'y') | ||
| 57 | ) | ||
| 58 | |||
| 59 | ax2.legend(loc=(0.65, 0.8)) | ||
| 60 | ax2.set_title('Frequencies of $x$ and $y$') | ||
| 61 | ax2.yaxis.tick_right() | ||
| 62 | |||
| 63 | x = [0,1,2,3,4,5] | ||
| 64 | y1 = [1,1,2,2,4,0] | ||
| 65 | y2 = [5,1,3,6,4,10] | ||
| 66 | y3 = [0,1,3,2,6,8] | ||
| 67 | |||
| 68 | fig, ax = plt.subplots() | ||
| 69 | |||
| 70 | ax.plot(x, y1, label = 'TEST1') | ||
| 71 | ax.plot(x, y2, label = 'ЕУЫЕ2') | ||
| 72 | ax.plot(x, y3, label = 'tmp3') | ||
| 73 | |||
| 74 | ax.legend() | ||
| 75 | |||
| 76 | #fig.set_figheight(5) | ||
| 77 | #fig.set_figwidth(8) | ||
| 78 | plt.show() | ||
| 79 | |||
| 80 | |||
| 81 | class Test(): | ||
| 82 | def __init__(self, _id, _data1, _data2): | ||
| 83 | self.id = _id | ||
| 84 | self.data1 = _data1 | ||
| 85 | self.data2 = _data2 | ||
| 86 | |||
| 87 | res = { | ||
| 88 | 1:Test(1, "12345", "54321"), | ||
| 89 | 2:Test(2, "11111", "aaaaa"), | ||
| 90 | 3:Test(3, "ddddd", "qwqwqw") | ||
| 91 | } | ||
| 92 | |||
| 93 | for val in res.keys(): | ||
| 94 | print(res[val].data1) | ||
| 95 | |||
| 96 | datetime_min = datetime.datetime(2020, 1, 29, 22, 50, 0) | ||
| 97 | timestamp = int(datetime_min.timestamp()) | ||
| 98 | png_path = r"d:\PYTHON\tests\test1\png" | ||
| 99 | file_path = "{}\\dj_286m_{}.png".format(png_path, timestamp) | ||
| 100 | print(file_path) | ||
| 101 | print(os.path.exists(file_path)) | ||
| 102 | |||
| 103 | zero = -1.06 | ||
| 104 | class RiverCrossSection(): | ||
| 105 | |||
| 106 | def __init__(self, _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): | ||
| 107 | # параметры трапеции | ||
| 108 | self._zero_wlevel = _zero_bsv | ||
| 109 | self._trap_a = _left_slope # ширина левого склона трапеции русла | ||
| 110 | self._trap_b = _bottom # ширина дна трапеции русла | ||
| 111 | self._trap_c = _right_slope # ширина правого склона трапеции русла | ||
| 112 | self._trap_d = _max_h # высота трапеции русла | ||
| 113 | if self._trap_d >= 0: | ||
| 114 | self._trap_leftCtg = self._trap_a / self._trap_d # котангенс левого угла трапеции русла | ||
| 115 | self._trap_rightCtg = self._trap_c / self._trap_d # котангенс правого угла трапеции русла | ||
| 116 | else: | ||
| 117 | self._trap_leftCtg = 0 # котангенс левого угла трапеции русла | ||
| 118 | self._trap_rightCtg = 0 # котангенс правого угла трапеции русла | ||
| 119 | |||
| 120 | self._i_rb_part = _i_bias # уклон русла | ||
| 121 | self._n_rb_part = _n_roughness # шероховатость русла | ||
| 122 | |||
| 123 | # площадь сечения (м^2) | ||
| 124 | def f_trap_area(self, h): | ||
| 125 | return self._trap_b * h + (self._trap_leftCtg + self._trap_rightCtg) * h * h / 2 | ||
| 126 | |||
| 127 | # смоченный периметр (м) | ||
| 128 | def f_trap_perimetr(self, h): | ||
| 129 | return self._trap_b + \ | ||
| 130 | math.sqrt(self._trap_leftCtg ** 2 + 1) * h + \ | ||
| 131 | math.sqrt(self._trap_rightCtg ** 2 + 1) * h | ||
| 132 | |||
| 133 | # гидрологический радиус | ||
| 134 | def f_hydro_r(self, h): | ||
| 135 | return self.f_trap_area(h) / self.f_trap_perimetr(h) | ||
| 136 | |||
| 137 | # скорость потока (м/с) | ||
| 138 | def f_flow_speed(self, h): | ||
| 139 | return self.f_hydro_r(h)**(2./3) * math.sqrt(self._i_rb_part) / self._n_rb_part | ||
| 140 | |||
| 141 | # расход воды (м^3/с) | ||
| 142 | def f_flow_rate(self, h): | ||
| 143 | if h <= 0.: | ||
| 144 | return 0. | ||
| 145 | return self.f_trap_area(h) * self.f_flow_speed(h) | ||
| 146 | |||
| 147 | # расход воды (м^3/с) | ||
| 148 | def f_flow_rate_by_bs_h(self, bs_h): | ||
| 149 | return self.f_flow_rate(bs_h - self._zero_wlevel) | ||
| 150 | |||
| 151 | # уровень воды (м), определяемый по расходу воды (м^3/с) | ||
| 152 | def high_by_flow_rate(self, flow_rate): | ||
| 153 | if flow_rate <= 0.: | ||
| 154 | return 0. | ||
| 155 | return newton_raphson(self.f_flow_rate, flow_rate, 1.) | ||
| 156 | |||
| 157 | # уровень воды (м), определяемый по расходу воды (м^3/с) по балтийской системе высот | ||
| 158 | def bs_water_level(self, flow_rate): | ||
| 159 | return self.high_by_flow_rate(flow_rate) + self._zero_wlevel | ||
| 160 | |||
| 161 | |||
| 162 | real34 = loca_data.GetLevel34() | ||
| 163 | get_flow = RiverCrossSection() | ||
| 164 | min_flow = 100 | ||
| 165 | max_flow = 0 | ||
| 166 | for key in real34.keys(): | ||
| 167 | real_level = real34[key] | ||
| 168 | #real_level = real_level - zero | ||
| 169 | flow = get_flow.f_flow_rate_by_bs_h(real_level) | ||
| 170 | |||
| 171 | if flow < min_flow: | ||
| 172 | min_flow = flow | ||
| 173 | |||
| 174 | if flow > max_flow: | ||
| 175 | max_flow = flow | ||
| 176 | |||
| 177 | print("{}-{}".format(real_level, flow)) | ||
| 178 | |||
| 179 | print("{}-{}".format(min_flow, max_flow)) | ||
| 180 | |||
| 181 | |||
| 182 | datetime_min = datetime.datetime(2020, 1, 29, 22, 50, 0) | ||
| 183 | datetime_max = datetime.datetime(2020, 2, 1, 0, 0, 0) | ||
| 184 | |||
| 185 | date_diff = datetime_max - datetime_min | ||
| 186 | print(date_diff.seconds / 600) | ||
| 187 | ''' | ||
| 188 | |||
| 189 | first_dic = dict(a = "123", b = 1.9, c = 567) | ||
| 190 | first_dic1 = dict(a = "124", b = 2.9, c = 1567) | ||
| 191 | first_dic2 = dict(a = "125", b = 3.9, c = 2567) | ||
| 192 | first_dic3 = dict(a = "126", b = 4.9, c = 3567) | ||
| 193 | first_dic35 = None | ||
| 194 | first_dic4 = dict(a = "127", b = 5.9, c = 4567) | ||
| 195 | secon_dic = dict(aa = "qwe", bb = 0.0, cc = 3214) | ||
| 196 | |||
| 197 | |||
| 198 | def GetAllValues(_dict_with_pref): | ||
| 199 | key_store = [] | ||
| 200 | value_store = [] | ||
| 201 | for dwp_k in _dict_with_pref.keys(): | ||
| 202 | dwp = _dict_with_pref[dwp_k] | ||
| 203 | if dwp is not None: | ||
| 204 | for k in dwp.keys(): | ||
| 205 | key_store.append(str(dwp_k) + "_" + str(k)) | ||
| 206 | value_store.append(str(dwp[k])) | ||
| 207 | |||
| 208 | return key_store, value_store | ||
| 209 | |||
| 210 | ks, vs = GetAllValues(dict(fd = first_dic, sd = secon_dic)) | ||
| 211 | |||
| 212 | #print("\t".join(ks)) | ||
| 213 | #print("\t".join(vs)) | ||
| 214 | |||
| 215 | #timestamp = int(_datetime.timestamp()) | ||
| 216 | #file_path = r"\png\dj_286m_{}.png".format(timestamp) | ||
| 217 | |||
| 218 | #print(os.listdir('.\\png\\')) | ||
| 219 | |||
| 220 | files = os.listdir('.\\png\\') | ||
| 221 | |||
| 222 | for f in files: | ||
| 223 | ts = int(f.replace("dj_286m_","").replace(".png","")) | ||
| 224 | dt = datetime.datetime.fromtimestamp(ts) | ||
| 225 | print(dt) | ||
| 226 | |||
| 227 | # 2. Ищем файл и формируем матрицу | ||
| 228 | #if not os.path.exists(os.path.abspath(os.curdir) + file_path): | ||
| 229 | # return result |
1.66 KB
1.63 KB
1.65 KB
1.65 KB
1.6 KB
1.66 KB
1.53 KB
1.58 KB
1.41 KB
1.26 KB
1.11 KB
966 Bytes
643 Bytes
708 Bytes
463 Bytes
484 Bytes
426 Bytes
356 Bytes
334 Bytes
353 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
1.25 KB
1.26 KB
1.23 KB
1.29 KB
1.42 KB
1.44 KB
1.41 KB
1.3 KB
1.44 KB
1.46 KB
1.6 KB
1.6 KB
1.6 KB
1.53 KB
1.46 KB
1.45 KB
1.47 KB
1.4 KB
1.48 KB
1.58 KB
1.58 KB
1.37 KB
1.26 KB
1.14 KB
1.25 KB
1.23 KB
1.05 KB
914 Bytes
1.03 KB
1023 Bytes
1.22 KB
1.53 KB
1.51 KB
1.31 KB
1.19 KB
1.26 KB
1.15 KB
1.32 KB
1.31 KB
1.25 KB
1.2 KB
1015 Bytes
930 Bytes
773 Bytes
651 Bytes
420 Bytes
712 Bytes
692 Bytes
726 Bytes
959 Bytes
659 Bytes
691 Bytes
801 Bytes
1.28 KB
1.32 KB
1.34 KB
1.02 KB
1.17 KB
1.06 KB
1.13 KB
1.17 KB
1.15 KB
1.15 KB
1.03 KB
1.32 KB
1.41 KB
1.45 KB
1.64 KB
1.54 KB
1.5 KB
1.53 KB
1.56 KB
1.43 KB
1.37 KB
1.39 KB
1.27 KB
1.34 KB
1.41 KB
1.3 KB
1.3 KB
1.52 KB
1.3 KB
1.13 KB
903 Bytes
946 Bytes
1 KB
958 Bytes
1.09 KB
1.25 KB
1.21 KB
1.07 KB
916 Bytes
1.2 KB
1.13 KB
1.22 KB
1.22 KB
1003 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
1.33 KB
1.36 KB
1.27 KB
1.25 KB
1.23 KB
1.24 KB
1.31 KB
1.09 KB
1011 Bytes
885 Bytes
1.04 KB
960 Bytes
872 Bytes
820 Bytes
840 Bytes
830 Bytes
891 Bytes
857 Bytes
723 Bytes
794 Bytes
752 Bytes
664 Bytes
717 Bytes
744 Bytes
750 Bytes
940 Bytes
897 Bytes
967 Bytes
1.02 KB
1 KB
1003 Bytes
972 Bytes
1008 Bytes
1.27 KB
1.14 KB
1.1 KB
1.13 KB
1.22 KB
996 Bytes
1.04 KB
1.06 KB
1.13 KB
1.25 KB
1.27 KB
935 Bytes
904 Bytes
567 Bytes
382 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
377 Bytes
623 Bytes
874 Bytes
1.02 KB
1.13 KB
1.25 KB
1.08 KB
1.15 KB
1.18 KB
1017 Bytes
925 Bytes
860 Bytes
594 Bytes
565 Bytes
514 Bytes
536 Bytes
577 Bytes
649 Bytes
850 Bytes
774 Bytes
972 Bytes
1 KB
922 Bytes
803 Bytes
493 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
874 Bytes
1.26 KB
1.47 KB
1.53 KB
1.65 KB
1.64 KB
1.67 KB
1.6 KB
1.64 KB
1.64 KB
1.66 KB
1.62 KB
1.47 KB
1.09 KB
1.01 KB
891 Bytes
746 Bytes
889 Bytes
782 Bytes
641 Bytes
806 Bytes
833 Bytes
503 Bytes
537 Bytes
437 Bytes
401 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
375 Bytes
334 Bytes
750 Bytes
884 Bytes
1.01 KB
926 Bytes
727 Bytes
676 Bytes
353 Bytes
334 Bytes
526 Bytes
455 Bytes
576 Bytes
876 Bytes
1.1 KB
1.35 KB
1.6 KB
1.35 KB
1.31 KB
1.45 KB
1.42 KB
1.16 KB
1.38 KB
1.42 KB
1.4 KB
1.45 KB
1.36 KB
1.24 KB
1.24 KB
1.41 KB
1.42 KB
1.21 KB
1.24 KB
1.29 KB
1.3 KB
1.26 KB
1.34 KB
1.29 KB
1.24 KB
1.37 KB
1.45 KB
1.36 KB
1.35 KB
1.4 KB
1.52 KB
1.39 KB
1.44 KB
1.25 KB
1.22 KB
1.47 KB
1.33 KB
1.58 KB
1.58 KB
1.44 KB
1.41 KB
1.42 KB
1.35 KB
1.45 KB
1.52 KB
1.33 KB
1.35 KB
1.42 KB
1.45 KB
1.39 KB
1.35 KB
1.48 KB
1.55 KB
1.55 KB
1.47 KB
1.49 KB
1.49 KB
1.42 KB
1.37 KB
1.49 KB
1.49 KB
1.59 KB
1.59 KB
1.57 KB
1.67 KB
1.59 KB
1.5 KB
1.61 KB
1.62 KB
1.62 KB
1.62 KB
1.58 KB
1.58 KB
1.48 KB
1.48 KB
1.62 KB
1.58 KB
1.51 KB
1.48 KB
1.34 KB
1.29 KB
1.51 KB
1.54 KB
1.62 KB
1.64 KB
1.5 KB
1.68 KB
1.65 KB
1.6 KB
1.62 KB
1.59 KB
1.36 KB
1.36 KB
1.41 KB
1.41 KB
1.64 KB
1.57 KB
1.48 KB
1.47 KB
1.38 KB
1.38 KB
1.33 KB
1.23 KB
1.18 KB
1.6 KB
1.53 KB
1.5 KB
1.46 KB
1.4 KB
1.26 KB
1.08 KB
1.15 KB
1.06 KB
1018 Bytes
1018 Bytes
1.04 KB
542 Bytes
1.38 KB
1.38 KB
1.58 KB
1.55 KB
1.55 KB
1.39 KB
1.5 KB
1.31 KB
1.33 KB
1.48 KB
1.47 KB
1.47 KB
1.28 KB
1.07 KB
1.07 KB
1.51 KB
1.4 KB
1.4 KB
1.45 KB
1.5 KB
1.49 KB
1.57 KB
1.38 KB
1.38 KB
1.17 KB
1.17 KB
695 Bytes
334 Bytes
334 Bytes
334 Bytes
375 Bytes
1.19 KB
1.41 KB
1.61 KB
1.63 KB
1.54 KB
1.45 KB
1.39 KB
1.28 KB
1.37 KB
1.53 KB
1.38 KB
1.23 KB
1.27 KB
1.27 KB
1.4 KB
1.45 KB
1.44 KB
1.36 KB
1.46 KB
1.28 KB
1.41 KB
1.27 KB
1.34 KB
1.19 KB
1.26 KB
1.3 KB
1.28 KB
1.1 KB
937 Bytes
1.14 KB
1.22 KB
1.2 KB
1.32 KB
1.29 KB
1.25 KB
1.12 KB
1.22 KB
1.29 KB
1.19 KB
1.39 KB
1.24 KB
1.25 KB
1.35 KB
1.35 KB
1.52 KB
1.33 KB
1.27 KB
1.33 KB
1.27 KB
1.39 KB
1.4 KB
1.4 KB
1.57 KB
1.66 KB
1.43 KB
1.54 KB
1.54 KB
1.57 KB
1.66 KB
1.56 KB
1.53 KB
1.36 KB
1.46 KB
1.3 KB
1.59 KB
1.51 KB
1.38 KB
1.53 KB
1.45 KB
1.5 KB
1.43 KB
1.29 KB
1.5 KB
1.58 KB
1.55 KB
1.66 KB
1.59 KB
1.68 KB
1.66 KB
1.61 KB
1.49 KB
1.21 KB
1001 Bytes
832 Bytes
903 Bytes
595 Bytes
576 Bytes
554 Bytes
628 Bytes
446 Bytes
544 Bytes
550 Bytes
547 Bytes
541 Bytes
856 Bytes
1.1 KB
1.07 KB
1.23 KB
1.29 KB
1.4 KB
1.29 KB
1.09 KB
1.21 KB
1.13 KB
1.48 KB
1.4 KB
1.56 KB
1.62 KB
1.5 KB
1.38 KB
1.44 KB
1.34 KB
1.35 KB
1.31 KB
1.25 KB
1.15 KB
992 Bytes
1000 Bytes
1.14 KB
1.26 KB
1.09 KB
1.11 KB
1.14 KB
1.11 KB
1.15 KB
1.27 KB
1.12 KB
1011 Bytes
1.23 KB
1.07 KB
759 Bytes
835 Bytes
833 Bytes
748 Bytes
742 Bytes
929 Bytes
1.04 KB
1.16 KB
1.14 KB
1.36 KB
1.27 KB
1.34 KB
1.01 KB
1.17 KB
1.42 KB
1.63 KB
1.63 KB
1.57 KB
1.6 KB
1.59 KB
1.72 KB
1.58 KB
1.59 KB
1.66 KB
1.38 KB
1.35 KB
1.32 KB
1.4 KB
1.66 KB
1.48 KB
1.52 KB
1.52 KB
1.51 KB
1.58 KB
1.63 KB
1.59 KB
1.53 KB
1.5 KB
1.49 KB
1.52 KB
1.54 KB
1.45 KB
1.31 KB
1.5 KB
1.55 KB
1.55 KB
1.36 KB
1.44 KB
1.29 KB
1.31 KB
1.39 KB
1.23 KB
1.53 KB
1.35 KB
1.36 KB
1.36 KB
1.51 KB
1.65 KB
1.57 KB
1.59 KB
1.28 KB
1.27 KB
1.14 KB
1.34 KB
1.27 KB
1.06 KB
1.28 KB
1.47 KB
1.47 KB
1.44 KB
1.38 KB
1.3 KB
1.34 KB
1.16 KB
1.05 KB
1.1 KB
1.11 KB
1.38 KB
1.33 KB
1.12 KB
1.12 KB
695 Bytes
400 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
725 Bytes
646 Bytes
334 Bytes
334 Bytes
334 Bytes
415 Bytes
334 Bytes
353 Bytes
726 Bytes
1.17 KB
1.49 KB
1.36 KB
1.39 KB
1.16 KB
831 Bytes
425 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
334 Bytes
790 Bytes
1.02 KB
1.04 KB
1.05 KB
1019 Bytes
881 Bytes
940 Bytes
1.16 KB
1.39 KB
1.38 KB
1.4 KB
1.47 KB
1.27 KB
1.21 KB
1.26 KB
1.31 KB
1.03 KB
912 Bytes
1006 Bytes
1.11 KB
1.07 KB
1.04 KB
1.3 KB
1.55 KB
1.63 KB
1.52 KB
1.44 KB
1.43 KB
1.55 KB
1.36 KB
1.21 KB
1.25 KB
1.43 KB
1.57 KB
1.51 KB
1.53 KB
1.44 KB
1.23 KB
1.44 KB
1.5 KB
1.31 KB
1.29 KB
1.35 KB
1.32 KB
1.33 KB
1.33 KB
1.4 KB
1.37 KB
1.38 KB
1.22 KB
1.27 KB
1.19 KB
1.44 KB
1.23 KB
1.18 KB
1.02 KB
852 Bytes
585 Bytes
413 Bytes
334 Bytes
334 Bytes
476 Bytes
623 Bytes
958 Bytes
1.26 KB
1.12 KB
1.52 KB
1.42 KB
1.15 KB
1.02 KB
1.02 KB
873 Bytes
1.11 KB
1.09 KB
1.2 KB
1.22 KB
1.19 KB
968 Bytes
1.28 KB
1.19 KB
1.41 KB
1.45 KB
1.54 KB
1.38 KB
1.32 KB
838 Bytes
431 Bytes
376 Bytes
789 Bytes
893 Bytes
732 Bytes
376 Bytes
334 Bytes
841 Bytes
912 Bytes
1.15 KB
837 Bytes
-
Please register or sign in to post a comment