##// END OF EJS Templates
Add static images and fix template
jespinoza -
r45:08ba8fe1a748
parent child
Show More
@@ -1,55 +1,82
1 version: '2'
1 version: '3'
2
2
3 services:
3 services:
4 web:
4 web:
5 container_name: 'realtime'
5 container_name: 'realtime'
6 build: .
6 build: .
7 restart: always
7 restart: always
8 image: realtime
8 image: realtime
9 command: python manage.py runserver 0.0.0.0:8000
9 # command: python manage.py runserver 0.0.0.0:8000
10 # command: gunicorn realtime.wsgi:application --bind 0.0.0.0:8080
11 command: daphne -b 0.0.0.0 -p 8080 realtime.asgi:application
10 env_file: .env
12 env_file: .env
11 ports:
13 # ports:
12 - "8000:8000"
14 # - "8081:8081"
15 # expose:
16 # - 8000
13 links:
17 links:
14 - redis
18 - redis
15 - mongo
19 - mongo
16 volumes:
20 volumes:
17 - './:${APP_DIR}'
21 - './:${APP_DIR}'
22 - './static:/static'
18 depends_on:
23 depends_on:
19 - redis
24 - redis
20 - mongo
25 - mongo
21
26
22 zmq_server:
27 zmq_server:
23 container_name: 'realtime_zmq'
28 container_name: 'realtime_zmq'
24 restart: always
29 restart: always
25 image: 'realtime'
30 image: 'realtime'
26 ports:
31 ports:
27 - '4444:4444'
32 - '4444:4444'
28 command: 'python -u scripts/server.py'
33 command: 'python -u scripts/server.py'
29 env_file: .env
34 env_file: .env
30 links:
35 links:
31 - redis
36 - redis
32 - mongo
37 - mongo
33 volumes:
38 volumes:
34 - './:${APP_DIR}'
39 - './:${APP_DIR}'
35 depends_on:
40 depends_on:
36 - web
41 - web
37
42
38 redis:
43 redis:
39 container_name: 'realtime_redis'
44 container_name: 'realtime_redis'
40 image: 'redis:3.2-alpine'
45 image: 'redis:5.0-alpine'
41 volumes:
46 volumes:
42 - 'redisdata:/data'
47 - '/data/dockers/realtime/redis:/data'
43
48
44 mongo:
49 mongo:
45 container_name: 'realtime_mongo'
50 container_name: 'realtime_mongo'
46 image: 'mongo:4.0'
51 image: 'mongo:4.0'
47 command: '--storageEngine wiredTiger'
52 command: '--storageEngine wiredTiger'
48 ports:
53 ports:
49 - '127.0.0.1:27017:27017'
54 - '127.0.0.1:27017:27017'
50 volumes:
55 volumes:
51 - 'mongodata:/data/db'
56 - '/data/dockers/realtime/mongo:/data/db'
57
58 #volumes:
59 # redisdata:
60 # mongodata:
61
62 nginx:
63 image: nginx:1.15-alpine
64 volumes:
65 - ./static:/static
66 - ./nginx:/etc/nginx/conf.d
67 - ./certbot/conf:/etc/letsencrypt
68 - ./certbot/www:/var/www/certbot
69 ports:
70 - "8000:8000"
71 - "443:443"
72 depends_on:
73 - web
74 command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
75
76 certbot:
77 image: certbot/certbot:latest
78 volumes:
79 - ./certbot/conf:/etc/letsencrypt
80 - ./certbot/www:/var/www/certbot
81 entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
52
82
53 volumes:
54 redisdata:
55 mongodata: No newline at end of file
@@ -1,138 +1,138
1 #!/usr/bin/python
1 #!/usr/bin/python
2 # -*- coding: UTF-8 -*-
2 # -*- coding: UTF-8 -*-
3 import os
3 import os
4 import json
4 import json
5 import simplejson
5 import simplejson
6 from datetime import datetime, timedelta
6 from datetime import datetime, timedelta
7 import numpy
7 import numpy
8 from pymongo import MongoClient
8 from pymongo import MongoClient
9 # import mongoengine
9 # import mongoengine
10 from asgiref.sync import async_to_sync
10 from asgiref.sync import async_to_sync
11 from channels.generic.websocket import WebsocketConsumer
11 from channels.generic.websocket import WebsocketConsumer
12
12
13 # from plotter.models import Experiment, ExpDetail, PlotMeta, PlotData
13 # from plotter.models import Experiment, ExpDetail, PlotMeta, PlotData
14
14
15 # Here we create the db named "dbplots"
15 # Here we create the db named "dbplots"
16 host = os.environ.get('HOST_MONGO', 'localhost')
16 host = os.environ.get('HOST_MONGO', 'localhost')
17 # mongoengine.connect('dbplots', host=host, port=27017)
17 # mongoengine.connect('dbplots', host=host, port=27017)
18
18
19 CLIENT = MongoClient('{}:27017'.format(host))
19 CLIENT = MongoClient('{}:27017'.format(host))
20 DB = CLIENT['dbplots']
20 DB = CLIENT['dbplots']
21
21
22 class MainConsumer(WebsocketConsumer):
22 class MainConsumer(WebsocketConsumer):
23
23
24 def connect(self):
24 def connect(self):
25 self.group_name = 'main'
25 self.group_name = 'main'
26 async_to_sync(self.channel_layer.group_add)(
26 async_to_sync(self.channel_layer.group_add)(
27 self.group_name,
27 self.group_name,
28 self.channel_name
28 self.channel_name
29 )
29 )
30 self.accept()
30 self.accept()
31
31
32 def disconnect(self, close_code):
32 def disconnect(self, close_code):
33 async_to_sync(self.channel_layer.group_discard)(
33 async_to_sync(self.channel_layer.group_discard)(
34 self.group_name,
34 self.group_name,
35 self.channel_name
35 self.channel_name
36 )
36 )
37
37
38 def receive(self, text_data):
38 def receive(self, text_data):
39 pass
39 pass
40
40
41 def zmq_message(self, event):
41 def zmq_message(self, event):
42 # Send message to WebSocket
42 # Send message to WebSocket
43 self.send(text_data=event['message'])
43 self.send(text_data=event['message'])
44
44
45 class PlotConsumer(WebsocketConsumer):
45 class PlotConsumer(WebsocketConsumer):
46
46
47 def connect(self):
47 def connect(self):
48
48
49 if 'realtime' in self.scope['path']:
49 if 'realtime' in self.scope['path']:
50 self.realtime = True
50 self.realtime = True
51 self.group_name = '{}_{}'.format(
51 self.group_name = '{}_{}'.format(
52 self.scope['url_route']['kwargs']['code'],
52 self.scope['url_route']['kwargs']['code'],
53 self.scope['url_route']['kwargs']['plot'],
53 self.scope['url_route']['kwargs']['plot'],
54 )
54 )
55
55
56 async_to_sync(self.channel_layer.group_add)(
56 async_to_sync(self.channel_layer.group_add)(
57 self.group_name,
57 self.group_name,
58 self.channel_name
58 self.channel_name
59 )
59 )
60 else:
60 else:
61 self.realtime = False
61 self.realtime = False
62 self.accept()
62 self.accept()
63
63
64 def disconnect(self, close_code):
64 def disconnect(self, close_code):
65
65
66 if self.realtime:
66 if self.realtime:
67 async_to_sync(self.channel_layer.group_discard)(
67 async_to_sync(self.channel_layer.group_discard)(
68 self.group_name,
68 self.group_name,
69 self.channel_name
69 self.channel_name
70 )
70 )
71
71
72 def receive(self, text_data):
72 def receive(self, text_data):
73 ret = {}
73 ret = {}
74 dt = datetime.strptime(text_data, '%d-%m-%Y')
74 dt = datetime.strptime(text_data, '%d-%m-%Y')
75 code = self.scope['url_route']['kwargs']['code']
75 code = self.scope['url_route']['kwargs']['code']
76 plot = self.scope['url_route']['kwargs']['plot']
76 plot = self.scope['url_route']['kwargs']['plot']
77 exp = DB.experiment.find_one({'code': int(code)})
77 exp = DB.experiment.find_one({'code': int(code)})
78 det0 = DB.exp_detail.find_one({
78 det0 = DB.exp_detail.find_one({
79 'experiment': exp['_id'],
79 'experiment': exp['_id'],
80 'date': dt-timedelta(days=1)
80 'date': dt-timedelta(days=1)
81 })
81 })
82 det1 = DB.exp_detail.find_one({
82 det1 = DB.exp_detail.find_one({
83 'experiment': exp['_id'],
83 'experiment': exp['_id'],
84 'date': dt
84 'date': dt
85 })
85 })
86
86
87 if det1:
87 if det1:
88 meta1 = DB.plot_meta.find_one({
88 meta1 = DB.plot_meta.find_one({
89 'exp_detail': det1['_id'],
89 'exp_detail': det1['_id'],
90 'plot': plot
90 'plot': plot
91 })
91 })
92 if meta1:
92 if meta1:
93 if meta1['metadata']['type'] in ('pcolor',):
93 if meta1['metadata']['type'] in ('pcolor', 'image'):
94 datas = DB.plot_data.find(
94 datas = DB.plot_data.find(
95 {'plot': meta1['_id']},
95 {'plot': meta1['_id']},
96 ['time', 'data'],
96 ['time', 'data'],
97 sort=[('time', -1)],
97 sort=[('time', -1)],
98 limit=1)[0]
98 limit=1)[0]
99 ret['time'] = [datas['time']]
99 ret['time'] = [datas['time']]
100 ret['data'] = datas['data']
100 ret['data'] = datas['data']
101 ret['metadata'] = meta1['metadata']
101 ret['metadata'] = meta1['metadata']
102 else:
102 else:
103 last = det1['last_time']
103 last = det1['last_time']
104 metas = [meta1['_id']]
104 metas = [meta1['_id']]
105 if det0:
105 if det0:
106 meta0 = DB.plot_meta.find_one({
106 meta0 = DB.plot_meta.find_one({
107 'exp_detail': det0['_id'],
107 'exp_detail': det0['_id'],
108 'plot': plot
108 'plot': plot
109 })
109 })
110 if meta0:
110 if meta0:
111 metas.append(meta0['_id'])
111 metas.append(meta0['_id'])
112 total = DB.plot_data.count_documents({
112 total = DB.plot_data.count_documents({
113 'plot': {'$in': metas},
113 'plot': {'$in': metas},
114 'time': {'$gt': last-12*60*60}
114 'time': {'$gt': last-12*60*60}
115 })
115 })
116 skip = 0 if total-720<0 else total-720
116 skip = 0 if total-720<0 else total-720
117 datas = DB.plot_data.find({
117 datas = DB.plot_data.find({
118 'plot': {'$in': metas},
118 'plot': {'$in': metas},
119 'time': {'$gt': last-12*60*60}
119 'time': {'$gt': last-12*60*60}
120 }, ['time', 'data'], sort=[('time', 1)], limit=720, skip=skip)
120 }, ['time', 'data'], sort=[('time', 1)], limit=720, skip=skip)
121
121
122 dum = [(d['time'], d['data']) for d in datas]
122 dum = [(d['time'], d['data']) for d in datas]
123 ret['time'] = [d[0] for d in dum]
123 ret['time'] = [d[0] for d in dum]
124 dum = numpy.array([d[1] for d in dum])
124 dum = numpy.array([d[1] for d in dum])
125
125
126 if len(dum[0][0])==1:
126 if len(dum[0][0])==1:
127 ret['data'] = dum.T[0].tolist()
127 ret['data'] = dum.T[0].tolist()
128 else:
128 else:
129 ret['data'] = [t for t in map(list, list(zip(*dum.tolist())))]
129 ret['data'] = [t for t in map(list, list(zip(*dum.tolist())))]
130 ret['metadata'] = meta1['metadata']
130 ret['metadata'] = meta1['metadata']
131
131
132 self.send(simplejson.dumps(ret, ignore_nan=True))
132 self.send(simplejson.dumps(ret, ignore_nan=True))
133 else:
133 else:
134 self.send(json.dumps({'interval': 0}))
134 self.send(json.dumps({'interval': 0}))
135
135
136 def zmq_message(self, event):
136 def zmq_message(self, event):
137 # Send message to WebSocket
137 # Send message to WebSocket
138 self.send(text_data=event['message'])
138 self.send(text_data=event['message'])
@@ -1,9 +1,9
1 from django.conf.urls import url
1 from django.urls import re_path
2
2
3 from . import consumers
3 from . import consumers
4
4
5 websocket_urlpatterns = [
5 websocket_urlpatterns = [
6 url(r'^ws/main/$', consumers.MainConsumer),
6 re_path(r'^ws/main/$', consumers.MainConsumer.as_asgi()),
7 url(r'^ws/realtime/(?P<code>[^/]+)/(?P<plot>[^/]+)/$', consumers.PlotConsumer),
7 re_path(r'^ws/realtime/(?P<code>[^/]+)/(?P<plot>[^/]+)/$', consumers.PlotConsumer.as_asgi()),
8 url(r'^ws/database/(?P<code>[^/]+)/(?P<plot>[^/]+)/$', consumers.PlotConsumer),
8 re_path(r'^ws/database/(?P<code>[^/]+)/(?P<plot>[^/]+)/$', consumers.PlotConsumer.as_asgi()),
9 ] No newline at end of file
9 ]
@@ -1,45 +1,45
1 {% load static %} {% load bootstrap4 %}
1 {% load static %} {% load bootstrap4 %}
2 <footer>
2 <footer>
3 <div class="container">
3 <div class="container">
4 <ul class="footer-contact">
4 <ul class="footer-contact">
5 <li>
5 <li>
6 <span class="fa fa-fax"></span><div><p>Atención al ciudadano</p>
6 <span class="fa fa-fax"></span><div><p>Atención al ciudadano</p>
7 <p>Lunes a Viernes de 8:30 a 16:30</p></div>
7 <p>Lunes a Viernes de 8:30 a 16:30</p></div>
8 </li>
8 </li>
9 <li>
9 <li>
10 <span class="fa fa-map-marker-alt"></span><div>
10 <span class="fa fa-map-marker-alt"></span><div>
11 <p>Calle Badajoz Nº 169 Urb. Mayorazgo</p>
11 <p>Calle Badajoz Nº 169 Urb. Mayorazgo</p>
12 <p>I Etapa Ate, Lima 15012 - Perú</p></div>
12 <p>I Etapa Ate, Lima 15012 - Perú</p></div>
13 </li>
13 </li>
14 <li>
14 <li>
15 <span class="fa fa-envelope"></span>
15 <span class="fa fa-envelope"></span>
16 roj@igp.gob.pe
16 roj@igp.gob.pe
17 </li>
17 </li>
18 <li>
18 <li>
19 <span class="fa fa-phone"></span>
19 <span class="fa fa-phone"></span>
20 (511)317-2313
20 (511)317-2313
21 </li>
21 </li>
22 </ul>
22 </ul>
23 <ul class="nav-social social-footer">
23 <ul class="nav-social social-footer">
24 <li>
24 <li>
25 <a href="https://www.facebook.com/igp.peru"><i class="fab fa-facebook-f"></i></a>
25 <a href="https://www.facebook.com/igp.peru"><i class="fab fa-facebook-f"></i></a>
26 </li>
26 </li>
27 <li>
27 <li>
28 <a href="https://twitter.com/igp_peru"><i class="fab fa-twitter"></i></a>
28 <a href="https://twitter.com/igp_peru"><i class="fab fa-twitter"></i></a>
29 </li>
29 </li>
30 <li>
30 <li>
31 <a href="https://www.linkedin.com/company/igpperu/"><i class="fab fa-linkedin-in"></i></a>
31 <a href="https://www.linkedin.com/company/igpperu/"><i class="fab fa-linkedin-in"></i></a>
32 </li>
32 </li>
33 <li>
33 <li>
34 <a href="https://www.instagram.com/igp.peru"><i class="fab fa-instagram"></i></a>
34 <a href="https://www.instagram.com/igp.peru"><i class="fab fa-instagram"></i></a>
35 </li>
35 </li>
36 <li>
36 <li>
37 <a href="https://www.youtube.com/igp_videos"><i class="fab fa-youtube"></i></a>
37 <a href="https://www.youtube.com/igp_videos"><i class="fab fa-youtube"></i></a>
38 </li>
38 </li>
39 </ul>
39 </ul>
40 </div>
40 </div>
41 <iframe class="map d-none d-sm-block"
41 <iframe class="map d-none d-sm-block"
42 src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d3901.828012758223!2d-76.94633793139629!3d-12.055351713347235!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x7ea774b6fa66a3c6!2sInstituto+Geof%C3%ADsico+del+Per%C3%BA!5e0!3m2!1ses-419!2spe!4v1545658855595"
42 src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d31226.562310315738!2d-76.89329626296218!3d-11.952312343404692!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x9105c3290814e129%3A0x61f92c3cfc90797b!2sRadio%20Observatorio%20de%20Jicamarca!5e0!3m2!1sen!2spe!4v1613758699300!5m2!1sen!2spe"
43 width="100%" height="100%" frameborder="0" allowfullscreen="false">&#160;
43 width="100%" height="100%" frameborder="0" allowfullscreen="false">&#160;
44 </iframe>
44 </iframe>
45 </footer> No newline at end of file
45 </footer>
@@ -1,64 +1,65
1 {% extends 'base.html' %}
1 {% extends 'base.html' %}
2 {% load static%}
2 {% load static%}
3 {% block extra-header %}
3 {% block extra-header %}
4 {% endblock %}
4 {% endblock %}
5 {% block sidebar_content %}
5 {% block sidebar_content %}
6 <nav class="nav flex-column">
6 <nav class="nav flex-column">
7 {% for tag in tags %}
7 {% for tag in tags %}
8 <a class="nav-link {{tag.active}}" href="{% url 'url_main' tag.name %}">{{tag.name | title}} &nbsp; <span class="badge badge-primary text-left">{{tag.n | stringformat:"02d"}} </span></a>
8 <a class="nav-link {{tag.active}}" href="{% url 'url_main' tag.name %}">{{tag.name | title}} &nbsp; <span class="badge badge-primary text-left">{{tag.n | stringformat:"02d"}} </span></a>
9 {% endfor %}
9 {% endfor %}
10 </nav>
10 </nav>
11 {% endblock %}
11 {% endblock %}
12 {% block content %}
12 {% block content %}
13 <div class="row">
13 <div class="row">
14 {% for exp in experiments %}
14 {% for exp in experiments %}
15 <div class="col-12 col-sm-6 col-md-4 col-lg-3 p-1">
15 <div class="col-12 col-sm-6 col-md-4 col-lg-3 p-1">
16 <div id="card_{{exp.code}}" class="card m-1 box-shadow text-{{exp.style}} border-{{exp.style}}">
16 <div id="card_{{exp.code}}" class="card m-1 box-shadow text-{{exp.style}} border-{{exp.style}}">
17 <div id="card_header_{{exp.code}}" class="card-header bg-{{exp.style}} text-white">{{exp.name}}</div>
17 <div id="card_header_{{exp.code}}" class="card-header bg-{{exp.style}} text-white">{{exp.name}}</div>
18 <div id="card_body_{{exp.code}}" class="card-body">
18 <div id="card_body_{{exp.code}}" class="card-body">
19 <div id="date_{{exp.code}}">Last data: {{exp.date | date:"H:i:s" }}</div>
19 <div id="date_{{exp.code}}">Last data: {{exp.date | date:"H:i:s" }}</div>
20 {% for plot in exp.plots %}
20 {% for plot in exp.plots %}
21 <a class="btn btn-sm btn-outline-{{exp.style}} mt-1" href="{% url 'url-plot' exp.code plot.plot %}" role="button">{{plot.name}}</a>
21 <a class="btn btn-sm btn-outline-{{exp.style}} mt-1" href="{% url 'url-plot' exp.code plot.plot %}" role="button">{{plot.name}}</a>
22 {% endfor %}
22 {% endfor %}
23 </div>
23 </div>
24 </div>
24 </div>
25 </div>
25 </div>
26 {% endfor %}
26 {% endfor %}
27 </div>
27 </div>
28 {% if experiments %}
28 {% if experiments %}
29 <div class="row">
29 <div class="row">
30 <ul class="legend">
30 <ul class="legend">
31 <li>Time format: 24h (UTC-5)</li>
31 <li>Time format: 24h (UTC-5)</li>
32 <li><i class="fas fa-circle text-success"></i><span>Instrument online</span></li>
32 <li><i class="fas fa-circle text-success"></i><span>Instrument online</span></li>
33 <li><i class="fas fa-circle text-warning"></i><span>Instrument delayed</span></li>
33 <li><i class="fas fa-circle text-warning"></i><span>Instrument delayed</span></li>
34 <li><i class="fas fa-circle text-danger"></i><span>Instrument offline</span></li>
34 <li><i class="fas fa-circle text-danger"></i><span>Instrument offline</span></li>
35 </ul>
35 </ul>
36 </div>
36 </div>
37 {% endif %}
37 {% endif %}
38 {% endblock %}
38 {% endblock %}
39 {% block script %}
39 {% block script %}
40 <script>
40 <script>
41 var socket = new WebSocket('ws://' + window.location.host +'/ws/main/');
41 var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
42 var socket = new WebSocket(ws_scheme + '://' + window.location.host +'/ws/main/');
42 socket.onopen = function open() {
43 socket.onopen = function open() {
43 console.log('Main WebSockets connection created.');
44 console.log('Main WebSockets connection created.');
44 };
45 };
45
46
46 socket.onmessage = function(event) {
47 socket.onmessage = function(event) {
47 var data = JSON.parse(event.data);
48 var data = JSON.parse(event.data);
48 // console.log(data);
49 // console.log(data);
49 var code = data['code'];
50 var code = data['code'];
50 console.log(code);
51 console.log(code);
51 var value = data['value'];
52 var value = data['value'];
52 var time = moment(new Date(data['time']*1000)).format('HH:mm:ss');
53 var time = moment(new Date(data['time']*1000)).format('HH:mm:ss');
53
54
54 $("#date_"+code).text("Last data: "+time);
55 $("#date_"+code).text("Last data: "+time);
55 $("#card_"+code).removeClass().addClass("card m-1 box-shadow text-"+value+" border-"+value);
56 $("#card_"+code).removeClass().addClass("card m-1 box-shadow text-"+value+" border-"+value);
56 $("#card_header_"+code).removeClass().addClass("card-header text-white bg-"+value);
57 $("#card_header_"+code).removeClass().addClass("card-header text-white bg-"+value);
57 $("#card_body_"+code).find("a").removeClass().addClass("btn btn-sm mt-1 btn-outline-"+value);
58 $("#card_body_"+code).find("a").removeClass().addClass("btn btn-sm mt-1 btn-outline-"+value);
58 };
59 };
59
60
60 if (socket.readyState == WebSocket.OPEN) {
61 if (socket.readyState == WebSocket.OPEN) {
61 socket.onopen();
62 socket.onopen();
62 };
63 };
63 </script>
64 </script>
64 {% endblock script %}
65 {% endblock script %}
@@ -1,105 +1,106
1 {% extends 'base.html' %} {% load static %} {% load bootstrap4 %}
1 {% extends 'base.html' %} {% load static %} {% load bootstrap4 %}
2
2
3 {% block sidebar_content %}
3 {% block sidebar_content %}
4 <h5>{{name}}</h5>
4 <h5>{{name}}</h5>
5 <nav class="nav flex-column">
5 <nav class="nav flex-column">
6 {% for plot in plots %}
6 {% for plot in plots %}
7 <a class="nav-link" href="{% url 'url-plot' code plot.plot %}">{{plot.name}}</a>
7 <a class="nav-link" href="{% url 'url-plot' code plot.plot %}">{{plot.name}}</a>
8 {% endfor %}
8 {% endfor %}
9 </nav>
9 </nav>
10 {% endblock %}
10 {% endblock %}
11
11
12 {% block content %}
12 {% block content %}
13 <div class="row justify-content-center">
13 <div class="row justify-content-center">
14 <div id="loader" class="spinner-border" role="status">
14 <div id="loader" class="spinner-border" role="status">
15 <span class="sr-only">Loading...</span>
15 <span class="sr-only">Loading...</span>
16 </div>
16 </div>
17 </div>
17 </div>
18 <div id="plot" {%if meta.metadata.type == 'pcolor' %}class="row"{%endif%}>
18 <div id="plot" {%if meta.metadata.type == 'pcolor' %}class="row"{%endif%}>
19 {% if image %}
19 {% if image %}
20 <img id="image" class="img-fluid"/>
20 <img id="image" class="img-fluid"/>
21 {% endif %}
21 {% endif %}
22 </div>
22 </div>
23 {% endblock content %}
23 {% endblock content %}
24
24
25 {% block modal %}
25 {% block modal %}
26 <!-- Modal -->
26 <!-- Modal -->
27 {% if setup_form %}
27 {% if setup_form %}
28 <div class="modal fade" id="setup" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
28 <div class="modal fade" id="setup" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
29 <div class="modal-dialog modal-sm" role="document">
29 <div class="modal-dialog modal-sm" role="document">
30 <div class="modal-content">
30 <div class="modal-content">
31 <div class="modal-header">
31 <div class="modal-header">
32 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
32 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
33 <span aria-hidden="true">&times;</span>
33 <span aria-hidden="true">&times;</span>
34 </button>
34 </button>
35 <h4 class="modal-title" id="myModalLabel">Setup plot</h4>
35 <h4 class="modal-title" id="myModalLabel">Setup plot</h4>
36 </div>
36 </div>
37 <div class="modal-body">
37 <div class="modal-body">
38 {% if code and plot %}
38 {% if code and plot %}
39 <form id="form_setup">
39 <form id="form_setup">
40 {% bootstrap_form setup_form layout='grid' size='small' %}
40 {% bootstrap_form setup_form layout='grid' size='small' %}
41 </form>
41 </form>
42 {% endif %}
42 {% endif %}
43 </div>
43 </div>
44 <div class="modal-footer">
44 <div class="modal-footer">
45 <button id="bt_update" type="button" class="btn btn-primary">Update</button>
45 <button id="bt_update" type="button" class="btn btn-primary">Update</button>
46 </div>
46 </div>
47 </div>
47 </div>
48 </div>
48 </div>
49 </div>
49 </div>
50 {% endif %}
50 {% endif %}
51 {% endblock modal%} {% block script %}
51 {% endblock modal%} {% block script %}
52 <script src="{% static 'js/jroplots.js' %}"></script>
52 <script src="{% static 'js/jroplots.js' %}"></script>
53 <script>
53 <script>
54 /* This conditional is used to know if we have to setup the data
54 /* This conditional is used to know if we have to setup the data
55 or just update the last data*/
55 or just update the last data*/
56 $("#loader").css("display", "block");
56 $("#loader").css("display", "block");
57 var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
57 {% if realtime %}
58 {% if realtime %}
58 var socket = new WebSocket('ws://' + window.location.host + '/ws/realtime/{{code}}/{{plot}}/');
59 var socket = new WebSocket(ws_scheme + '://' + window.location.host + '/ws/realtime/{{code}}/{{plot}}/');
59 {% else %}
60 {% else %}
60 var socket = new WebSocket('ws://' + window.location.host + '/ws/database/{{code}}/{{plot}}/');
61 var socket = new WebSocket(ws_scheme + '://' + window.location.host + '/ws/database/{{code}}/{{plot}}/');
61 {% endif %}
62 {% endif %}
62 socket.onopen = function open() {
63 socket.onopen = function open() {
63 console.log('WebSockets connection created: ' + socket.url);
64 console.log('WebSockets connection created: ' + socket.url);
64 socket.send('{{date}}')
65 socket.send('{{date}}')
65 };
66 };
66
67
67 socket.onmessage = function message(event) {
68 socket.onmessage = function message(event) {
68 var data = JSON.parse(event.data);
69 var data = JSON.parse(event.data);
69 if (data.interval == 0) {
70 if (data.interval == 0) {
70 $("#loader").removeClass("loader").addClass("no-data");
71 $("#loader").removeClass("loader").addClass("no-data");
71 $("#loader").html("No data found");
72 $("#loader").html("No data found");
72 } else {
73 } else {
73 var first = plot(data);
74 var first = plot(data);
74 if (first == true) {
75 if (first == true) {
75 $("#loader").css("display", "none");
76 $("#loader").css("display", "none");
76 }
77 }
77 }
78 }
78 }
79 }
79
80
80 if (socket.readyState == WebSocket.OPEN) {
81 if (socket.readyState == WebSocket.OPEN) {
81 socket.onopen();
82 socket.onopen();
82 }
83 }
83
84
84 let flag = true;
85 let flag = true;
85 function plot(data) {
86 function plot(data) {
86 if (flag === true) {
87 if (flag === true) {
87 flag = false;
88 flag = false;
88 plt = new {{ fn_plot }} ({
89 plt = new {{ fn_plot }} ({
89 div: 'plot',
90 div: 'plot',
90 data: data,
91 data: data,
91 });
92 });
92 return true;
93 return true;
93 } else {
94 } else {
94 plt.update(data);
95 plt.update(data);
95 return false;
96 return false;
96 }
97 }
97 }
98 }
98 /*It is the button to make changes in my plot parameters defined in block modal*/
99 /*It is the button to make changes in my plot parameters defined in block modal*/
99 $("#bt_update").click(function () {
100 $("#bt_update").click(function () {
100 $("#setup").modal('hide');
101 $("#setup").modal('hide');
101 var values = $("#form_setup").serializeArray();
102 var values = $("#form_setup").serializeArray();
102 plt.restyle(values);
103 plt.restyle(values);
103 });
104 });
104
105
105 </script> {% endblock script %} No newline at end of file
106 </script> {% endblock script %}
@@ -1,238 +1,238
1 #!/usr/bin/python
1 #!/usr/bin/python
2 # -*- coding: UTF-8 -*-
2 # -*- coding: UTF-8 -*-
3
3
4
4
5 import os
5 import os
6 import time
6 import time
7 from datetime import datetime
7 from datetime import datetime
8
8
9 from django import forms
9 from django import forms
10 from django.contrib import messages
10 from django.contrib import messages
11 from django.utils.safestring import mark_safe
11 from django.utils.safestring import mark_safe
12 from django.shortcuts import render
12 from django.shortcuts import render
13 from django.http import HttpResponse
13 from django.http import HttpResponse
14
14
15 import mongoengine
15 import mongoengine
16
16
17 from plotter.models import Experiment, ExpDetail, PlotMeta, PlotData
17 from plotter.models import Experiment, ExpDetail, PlotMeta, PlotData
18
18
19 from utils.plots import skynoise_plot
19 from utils.plots import skynoise_plot
20
20
21 host = os.environ.get('HOST_MONGO', 'localhost')
21 host = os.environ.get('HOST_MONGO', 'localhost')
22 mongoengine.connect('dbplots', host=host, port=27017)
22 mongoengine.connect('dbplots', host=host, port=27017)
23
23
24
24
25 # Forms
25 # Forms
26 class SearchForm(forms.Form):
26 class SearchForm(forms.Form):
27
27
28 experiment = forms.ChoiceField()
28 experiment = forms.ChoiceField()
29 plot = forms.ChoiceField()
29 plot = forms.ChoiceField()
30
30
31 def __init__(self, *args, **kwargs):
31 def __init__(self, *args, **kwargs):
32
32
33 exp_choices = kwargs.pop('exp_choices', [])
33 exp_choices = kwargs.pop('exp_choices', [])
34 plt_choices = kwargs.pop('plt_choices', [])
34 plt_choices = kwargs.pop('plt_choices', [])
35 super(SearchForm, self).__init__(*args, **kwargs)
35 super(SearchForm, self).__init__(*args, **kwargs)
36 self.fields['experiment'].choices = [(0, 'Select Experiment')] + exp_choices
36 self.fields['experiment'].choices = [(0, 'Select Experiment')] + exp_choices
37 self.fields['plot'].choices = [(0, 'Select Plot')] + plt_choices
37 self.fields['plot'].choices = [(0, 'Select Plot')] + plt_choices
38 # we use this class to change the parameter in Scatter plot using the function plotly.restyle in jroplot.js
38 # we use this class to change the parameter in Scatter plot using the function plotly.restyle in jroplot.js
39 class ScatterSetupForm(forms.Form):
39 class ScatterSetupForm(forms.Form):
40
40
41 plotdiv = forms.CharField(widget=forms.HiddenInput())
41 plotdiv = forms.CharField(widget=forms.HiddenInput())
42 ymax = forms.CharField(initial=30)
42 ymax = forms.CharField(initial=30)
43 ymin = forms.CharField(initial=10)
43 ymin = forms.CharField(initial=10)
44
44
45 # we use this class to change the parameter in RTI plot using the function plotly.restyle in jroplot.js
45 # we use this class to change the parameter in RTI plot using the function plotly.restyle in jroplot.js
46 class RTISetupForm(forms.Form):
46 class RTISetupForm(forms.Form):
47
47
48 plotdiv = forms.CharField(widget=forms.HiddenInput())
48 plotdiv = forms.CharField(widget=forms.HiddenInput())
49 colormap = forms.ChoiceField(choices=[('Jet', 'Jet'), ('Viridis', 'Viridis'), ('RdBu', 'RdBu')])
49 colormap = forms.ChoiceField(choices=[('Jet', 'Jet'), ('Viridis', 'Viridis'), ('RdBu', 'RdBu')])
50 zmax = forms.CharField(initial=30)
50 zmax = forms.CharField(initial=30)
51 zmin = forms.CharField(initial=10)
51 zmin = forms.CharField(initial=10)
52 ymax = forms.CharField(initial=180)
52 ymax = forms.CharField(initial=180)
53 ymin = forms.CharField(initial=80)
53 ymin = forms.CharField(initial=80)
54
54
55 # we use this class to change the parameter in SPC plot using the function plotly.restyle in jroplot.js
55 # we use this class to change the parameter in SPC plot using the function plotly.restyle in jroplot.js
56 class SPCSetupForm(forms.Form):
56 class SPCSetupForm(forms.Form):
57
57
58 plotdiv = forms.CharField(widget=forms.HiddenInput())
58 plotdiv = forms.CharField(widget=forms.HiddenInput())
59 colormap = forms.ChoiceField(choices=[('Jet', 'Jet'), ('Viridis', 'Viridis'), ('RdBu', 'RdBu')])
59 colormap = forms.ChoiceField(choices=[('Jet', 'Jet'), ('Viridis', 'Viridis'), ('RdBu', 'RdBu')])
60 #como es un perfil xmin y xmax deben ser iguales a zmin y zmax
60 #como es un perfil xmin y xmax deben ser iguales a zmin y zmax
61 xmax = forms.CharField(initial=30)
61 xmax = forms.CharField(initial=30)
62 xmin = forms.CharField(initial=10)
62 xmin = forms.CharField(initial=10)
63 #x2max = forms.CharField(initial=30)
63 #x2max = forms.CharField(initial=30)
64 #x2min = forms.CharField(initial=10)
64 #x2min = forms.CharField(initial=10)
65 ymax = forms.CharField(initial=180)
65 ymax = forms.CharField(initial=180)
66 ymin = forms.CharField(initial=80)
66 ymin = forms.CharField(initial=80)
67 zmax = forms.CharField(initial=30)
67 zmax = forms.CharField(initial=30)
68 zmin = forms.CharField(initial=10)
68 zmin = forms.CharField(initial=10)
69
69
70 # Create your views here.
70 # Create your views here.
71 def main(request, tag=None):
71 def main(request, tag=None):
72
72
73 kwargs = {}
73 kwargs = {}
74 date = request.GET.get('date', datetime.utcnow().strftime('%d-%m-%Y'))
74 date = request.GET.get('date', datetime.now().strftime('%d-%m-%Y'))
75 exps = ExpDetail.objects(date=datetime.strptime(date, '%d-%m-%Y'))
75 exps = ExpDetail.objects(date=datetime.strptime(date, '%d-%m-%Y'))
76
76
77 tmp = {}
77 tmp = {}
78 for exp in exps:
78 for exp in exps:
79 label = exp.tag.lower().strip() if exp.tag else 'other'
79 label = exp.tag.lower().strip() if exp.tag else 'other'
80 if label in tmp:
80 if label in tmp:
81 tmp[label] += 1
81 tmp[label] += 1
82 else:
82 else:
83 tmp[label] = 1
83 tmp[label] = 1
84 tags = []
84 tags = []
85
85
86 for key, value in tmp.items():
86 for key, value in tmp.items():
87 if tag == key:
87 if tag == key:
88 tags.append({'name': key, 'n': tmp[key], 'active': 'active'})
88 tags.append({'name': key, 'n': tmp[key], 'active': 'active'})
89 else:
89 else:
90 tags.append({'name': key, 'n': tmp[key]})
90 tags.append({'name': key, 'n': tmp[key]})
91
91
92 kwargs['tags'] = tags
92 kwargs['tags'] = tags
93
93
94 if tag:
94 if tag:
95 experiments = []
95 experiments = []
96 for exp in exps:
96 for exp in exps:
97 label = exp.tag.lower().strip() if exp.tag else 'other'
97 label = exp.tag.lower().strip() if exp.tag else 'other'
98 if label != tag:
98 if label != tag:
99 continue
99 continue
100 dum = {}
100 dum = {}
101 dum['code'] = exp.experiment.code
101 dum['code'] = exp.experiment.code
102 dum['plots'] = []
102 dum['plots'] = []
103 dum['name'] = exp.experiment.name
103 dum['name'] = exp.experiment.name
104
104
105 t = time.time()
105 t = time.time()
106
106
107 if (t-exp['last_time']) > 6*exp['interval']:
107 if (t-exp['last_time']) > 6*exp['interval']:
108 status = 'Offline'
108 status = 'Offline'
109 clase = 'alertas-offline'
109 clase = 'alertas-offline'
110 style = 'danger'
110 style = 'danger'
111 elif (t-exp['last_time']) > 3*exp['interval']:
111 elif (t-exp['last_time']) > 3*exp['interval']:
112 status = 'Delayed'
112 status = 'Delayed'
113 clase = 'alertas-delayed'
113 clase = 'alertas-delayed'
114 style = 'warning'
114 style = 'warning'
115 else:
115 else:
116 status = 'Online'
116 status = 'Online'
117 clase = 'alertas-online'
117 clase = 'alertas-online'
118 style = 'success'
118 style = 'success'
119
119
120 dum['status'] = status
120 dum['status'] = status
121 dum['class'] = clase
121 dum['class'] = clase
122 dum['style']= style
122 dum['style']= style
123 dum['date']= datetime.fromtimestamp(exp['last_time'])
123 dum['date']= datetime.fromtimestamp(exp['last_time'])
124 for plot in exp.plots():
124 for plot in exp.plots():
125 dum['plots'].append({'plot': plot.plot, 'name': plot.plot.replace('_', ' ').title(), 'id':plot.id})
125 dum['plots'].append({'plot': plot.plot, 'name': plot.plot.replace('_', ' ').title(), 'id':plot.id})
126 experiments.append(dum)
126 experiments.append(dum)
127
127
128 kwargs['experiments'] = experiments
128 kwargs['experiments'] = experiments
129 kwargs['tag'] = tag
129 kwargs['tag'] = tag
130
130
131 kwargs['date'] = date
131 kwargs['date'] = date
132 kwargs['title'] = 'Home'
132 kwargs['title'] = 'Home'
133 kwargs['sidebar'] = True
133 kwargs['sidebar'] = True
134
134
135 return render(request, 'home.html', kwargs)
135 return render(request, 'home.html', kwargs)
136
136
137 def about(request):
137 def about(request):
138 '''
138 '''
139 '''
139 '''
140 kwargs = {
140 kwargs = {
141 'title': 'About'
141 'title': 'About'
142 }
142 }
143 return render(request, 'about.html', kwargs)
143 return render(request, 'about.html', kwargs)
144
144
145
145
146 def tools(request):
146 def tools(request):
147 '''
147 '''
148 '''
148 '''
149 kwargs = {
149 kwargs = {
150 'title': 'Tools',
150 'title': 'Tools',
151 'doy': (datetime.today().date()-datetime.today().date().replace(month=1, day=1)).days + 1
151 'doy': (datetime.today().date()-datetime.today().date().replace(month=1, day=1)).days + 1
152 }
152 }
153 return render(request, 'tools.html', kwargs)
153 return render(request, 'tools.html', kwargs)
154
154
155 def reports(request):
155 def reports(request):
156 '''
156 '''
157 '''
157 '''
158 kwargs = {
158 kwargs = {
159 'title': 'Reports',
159 'title': 'Reports',
160 }
160 }
161 return render(request, 'reports.html', kwargs)
161 return render(request, 'reports.html', kwargs)
162
162
163 def plot(request, code=None, plot=None):
163 def plot(request, code=None, plot=None):
164 '''
164 '''
165 '''
165 '''
166
166
167 realtime = False
167 realtime = False
168 date = request.GET.get('date', None)
168 date = request.GET.get('date', None)
169 if date is None:
169 if date is None:
170 date = datetime.utcnow().strftime('%d-%m-%Y')
170 date = datetime.now().strftime('%d-%m-%Y')
171 realtime = True
171 realtime = True
172 exp = Experiment.objects.get(code=int(code))
172 exp = Experiment.objects.get(code=int(code))
173 detail = ExpDetail.objects.get(experiment=exp, date=datetime.strptime(date, '%d-%m-%Y'))
173 detail = ExpDetail.objects.get(experiment=exp, date=datetime.strptime(date, '%d-%m-%Y'))
174 meta = PlotMeta.objects.get(exp_detail=detail, plot=plot)
174 meta = PlotMeta.objects.get(exp_detail=detail, plot=plot)
175 tag = detail.tag.lower().strip() if detail.tag else 'other'
175 tag = detail.tag.lower().strip() if detail.tag else 'other'
176
176
177 kwargs = {
177 kwargs = {
178 'code': code,
178 'code': code,
179 'plot': plot,
179 'plot': plot,
180 'meta':meta,
180 'meta':meta,
181 'date': date,
181 'date': date,
182 'id': meta.pk,
182 'id': meta.pk,
183 'realtime': realtime,
183 'realtime': realtime,
184 'title': 'Home',
184 'title': 'Home',
185 'name' : exp.name,
185 'name' : exp.name,
186 'sidebar': True,
186 'sidebar': True,
187 'tag' : tag,
187 'tag' : tag,
188 'plots': []
188 'plots': []
189 }
189 }
190
190
191 for plt in detail.plots():
191 for plt in detail.plots():
192 kwargs['plots'].append({'plot': plt.plot, 'name': plt.plot.replace('_', ' ').title()})
192 kwargs['plots'].append({'plot': plt.plot, 'name': plt.plot.replace('_', ' ').title()})
193
193
194 # Logic to show my views
194 # Logic to show my views
195 if meta.metadata['type'] == 'pcolorbuffer':
195 if meta.metadata['type'] == 'pcolorbuffer':
196 kwargs['setup_form'] = RTISetupForm()
196 kwargs['setup_form'] = RTISetupForm()
197 kwargs['fn_plot'] = 'PcolorBuffer'
197 kwargs['fn_plot'] = 'PcolorBuffer'
198 return render(request, 'plot.html', kwargs)
198 return render(request, 'plot.html', kwargs)
199 elif meta.metadata['type'] == 'pcolor':
199 elif meta.metadata['type'] == 'pcolor':
200 kwargs['setup_form'] = SPCSetupForm()
200 kwargs['setup_form'] = SPCSetupForm()
201 kwargs['fn_plot'] = 'Pcolor'
201 kwargs['fn_plot'] = 'Pcolor'
202 return render(request, 'plot.html', kwargs)
202 return render(request, 'plot.html', kwargs)
203 elif meta.metadata['type'] == 'scatterbuffer':
203 elif meta.metadata['type'] == 'scatterbuffer':
204 kwargs['setup_form'] = ScatterSetupForm()
204 kwargs['setup_form'] = ScatterSetupForm()
205 kwargs['fn_plot'] = 'ScatterBuffer'
205 kwargs['fn_plot'] = 'ScatterBuffer'
206 return render(request, 'plot.html', kwargs)
206 return render(request, 'plot.html', kwargs)
207 elif meta.metadata['type'] == 'image':
207 elif meta.metadata['type'] == 'image':
208 kwargs['image'] = True
208 kwargs['image'] = True
209 kwargs['fn_plot'] = 'StaticPlot'
209 kwargs['fn_plot'] = 'StaticPlot'
210 return render(request, 'plot.html', kwargs)
210 return render(request, 'plot.html', kwargs)
211 else:
211 else:
212 return render(request, 'home.html', {})
212 return render(request, 'home.html', {})
213
213
214 def plot_skynoise(request):
214 def plot_skynoise(request):
215
215
216 date = request.GET.get('date', None)
216 date = request.GET.get('date', None)
217 if date is None:
217 if date is None:
218 date = datetime.now()
218 date = datetime.now()
219 else:
219 else:
220 date = datetime.strptime(date, '%Y-%m-%d')
220 date = datetime.strptime(date, '%Y-%m-%d')
221
221
222 data = skynoise_plot(date.year, date.month, date.day)
222 data = skynoise_plot(date.year, date.month, date.day)
223 response = HttpResponse(data.getvalue(), content_type='image/png')
223 response = HttpResponse(data.getvalue(), content_type='image/png')
224
224
225 return response
225 return response
226
226
227 def plot_overjro(request):
227 def plot_overjro(request):
228
228
229 date = request.GET.get('date', None)
229 date = request.GET.get('date', None)
230 if date is None:
230 if date is None:
231 date = datetime.now()
231 date = datetime.now()
232 else:
232 else:
233 date = datetime.strptime(date, '%Y-%m-%d')
233 date = datetime.strptime(date, '%Y-%m-%d')
234
234
235 data = skynoise_plot(date.year, date.month, date.day)
235 data = skynoise_plot(date.year, date.month, date.day)
236 response = HttpResponse(data.getvalue(), content_type='image/png')
236 response = HttpResponse(data.getvalue(), content_type='image/png')
237
237
238 return response No newline at end of file
238 return response
@@ -1,137 +1,139
1 """
1 """
2 Django settings for realtime project.
2 Django settings for realtime project.
3
3
4 Generated by 'django-admin startproject' using Django 1.11.7.
4 Generated by 'django-admin startproject' using Django 1.11.7.
5
5
6 For more information on this file, see
6 For more information on this file, see
7 https://docs.djangoproject.com/en/1.11/topics/settings/
7 https://docs.djangoproject.com/en/1.11/topics/settings/
8
8
9 For the full list of settings and their values, see
9 For the full list of settings and their values, see
10 https://docs.djangoproject.com/en/1.11/ref/settings/
10 https://docs.djangoproject.com/en/1.11/ref/settings/
11 """
11 """
12
12
13 import os
13 import os
14
14
15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17
17
18
18
19 # Quick-start development settings - unsuitable for production
19 # Quick-start development settings - unsuitable for production
20 # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
20 # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
21
21
22 # SECURITY WARNING: keep the secret key used in production secret!
22 # SECURITY WARNING: keep the secret key used in production secret!
23 SECRET_KEY = '-rgo(&lgs^!4jn6atk_^=!a)+jtt%%h48a_w5-csgn7jc@iao5'
23 SECRET_KEY = '-rgo(&lgs^!4jn6atk_^=!a)+jtt%%h48a_w5-csgn7jc@iao5'
24
24
25 # SECURITY WARNING: don't run with debug turned on in production!
25 # SECURITY WARNING: don't run with debug turned on in production!
26 DEBUG = True
26 DEBUG = True
27
27
28 ALLOWED_HOSTS = ['*'] #YONG
28 ALLOWED_HOSTS = ['*'] #YONG
29
29
30
30
31 # Application definition
31 # Application definition
32
32
33 INSTALLED_APPS = [
33 INSTALLED_APPS = [
34 'django.contrib.admin',
34 'django.contrib.admin',
35 'django.contrib.auth',
35 'django.contrib.auth',
36 'django.contrib.contenttypes',
36 'django.contrib.contenttypes',
37 'django.contrib.sessions',
37 'django.contrib.sessions',
38 'django.contrib.messages',
38 'django.contrib.messages',
39 'django.contrib.staticfiles',
39 'django.contrib.staticfiles',
40 'bootstrap4',
40 'bootstrap4',
41 'channels',
41 'channels',
42 'plotter',
42 'plotter',
43 ]
43 ]
44
44
45 MIDDLEWARE = [
45 MIDDLEWARE = [
46 'django.middleware.security.SecurityMiddleware',
46 'django.middleware.security.SecurityMiddleware',
47 'django.contrib.sessions.middleware.SessionMiddleware',
47 'django.contrib.sessions.middleware.SessionMiddleware',
48 'django.middleware.common.CommonMiddleware',
48 'django.middleware.common.CommonMiddleware',
49 'django.middleware.csrf.CsrfViewMiddleware',
49 'django.middleware.csrf.CsrfViewMiddleware',
50 'django.contrib.auth.middleware.AuthenticationMiddleware',
50 'django.contrib.auth.middleware.AuthenticationMiddleware',
51 'django.contrib.messages.middleware.MessageMiddleware',
51 'django.contrib.messages.middleware.MessageMiddleware',
52 'django.middleware.clickjacking.XFrameOptionsMiddleware',
52 'django.middleware.clickjacking.XFrameOptionsMiddleware',
53 ]
53 ]
54
54
55 ROOT_URLCONF = 'realtime.urls'
55 ROOT_URLCONF = 'realtime.urls'
56
56
57 TEMPLATES = [
57 TEMPLATES = [
58 {
58 {
59 'BACKEND': 'django.template.backends.django.DjangoTemplates',
59 'BACKEND': 'django.template.backends.django.DjangoTemplates',
60 'DIRS': [],
60 'DIRS': [],
61 'APP_DIRS': True,
61 'APP_DIRS': True,
62 'OPTIONS': {
62 'OPTIONS': {
63 'context_processors': [
63 'context_processors': [
64 'django.template.context_processors.debug',
64 'django.template.context_processors.debug',
65 'django.template.context_processors.request',
65 'django.template.context_processors.request',
66 'django.contrib.auth.context_processors.auth',
66 'django.contrib.auth.context_processors.auth',
67 'django.contrib.messages.context_processors.messages',
67 'django.contrib.messages.context_processors.messages',
68 ],
68 ],
69 },
69 },
70 },
70 },
71 ]
71 ]
72
72
73 WSGI_APPLICATION = 'realtime.wsgi.application'
73 # WSGI_APPLICATION = 'realtime.wsgi.application'
74
74
75
75
76 # Database
76 # Database
77 # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
77 # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
78
78
79 DATABASES = {
79 DATABASES = {
80 'default': {
80 'default': {
81 'ENGINE': 'django.db.backends.sqlite3',
81 'ENGINE': 'django.db.backends.sqlite3',
82 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
82 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
83 }
83 }
84 }
84 }
85
85
86
86
87 # Password validation
87 # Password validation
88 # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
88 # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
89
89
90 AUTH_PASSWORD_VALIDATORS = [
90 AUTH_PASSWORD_VALIDATORS = [
91 {
91 {
92 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
92 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
93 },
93 },
94 {
94 {
95 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
95 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
96 },
96 },
97 {
97 {
98 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
98 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
99 },
99 },
100 {
100 {
101 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
101 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
102 },
102 },
103 ]
103 ]
104
104
105
105
106 # Internationalization
106 # Internationalization
107 # https://docs.djangoproject.com/en/1.11/topics/i18n/
107 # https://docs.djangoproject.com/en/1.11/topics/i18n/
108
108
109 LANGUAGE_CODE = 'en-us'
109 LANGUAGE_CODE = 'en-us'
110
110
111 TIME_ZONE = os.environ.get('TZ', 'UTC')
111 TIME_ZONE = os.environ.get('TZ', 'UTC')
112
112
113 USE_I18N = True
113 USE_I18N = True
114
114
115 USE_L10N = True
115 USE_L10N = True
116
116
117 USE_TZ = True
117 USE_TZ = True
118
118
119
119
120 # Static files (CSS, JavaScript, Images)
120 # Static files (CSS, JavaScript, Images)
121 # https://docs.djangoproject.com/en/1.11/howto/static-files/
121 # https://docs.djangoproject.com/en/1.11/howto/static-files/
122
122
123 STATIC_URL = '/static/'
123 STATIC_URL = '/static/'
124 STATIC_ROOT = '/static/'
124
125
125 #======================== YONG ================================
126 #======================== YONG ================================
126 host = os.environ.get('HOST_REDIS', '127.0.0.1')
127 host = os.environ.get('HOST_REDIS', '127.0.0.1')
127
128
129 ASGI_APPLICATION = 'realtime.asgi.application'
130
128 CHANNEL_LAYERS = {
131 CHANNEL_LAYERS = {
129 "default": {
132 "default": {
130 'BACKEND': 'channels_redis.core.RedisChannelLayer',
133 'BACKEND': 'channels_redis.core.RedisChannelLayer',
131 "CONFIG": {
134 "CONFIG": {
132 "hosts": [(host, 6379)],
135 "hosts": [(host, 6379)],
133 },
136 },
134 },
137 },
135 }
138 }
136
139
137 ASGI_APPLICATION = "realtime.routing.application"
@@ -1,13 +1,14
1 Django
1 Django
2 django-bootstrap4
2 django-bootstrap4
3 channels
3 channels
4 channels_redis
4 channels_redis
5 mongoengine
5 mongoengine
6 pymongo
6 pymongo
7 pyzmq
7 pyzmq
8 redis
8 redis
9 requests
9 requests
10 simplejson
10 simplejson
11 numpy
11 numpy
12 matplotlib
12 matplotlib
13 scipy No newline at end of file
13 scipy
14 gunicorn
@@ -1,142 +1,146
1 [
1 [
2 {
2 {
3 "code" : 100,
3 "code" : 100,
4 "name" : "HF JRO"
4 "name" : "HF JRO"
5 },
5 },
6 {
6 {
7 "code" : 101,
7 "code" : 101,
8 "name" : "HF huancayo"
8 "name" : "HF huancayo"
9 },
9 },
10 {
10 {
11 "code" : 102,
11 "code" : 102,
12 "name" : "HF Ica"
12 "name" : "HF Ica"
13 },
13 },
14 {
14 {
15 "code" : 110,
15 "code" : 110,
16 "name" : "ISR EW Drifts"
16 "name" : "ISR EW Drifts"
17 },
17 },
18 {
18 {
19 "code" : 111,
19 "code" : 111,
20 "name" : "ISR Faraday"
20 "name" : "ISR Faraday"
21 },
21 },
22 {
22 {
23 "code" : 112,
23 "code" : 112,
24 "name" : "ISR Imaging"
24 "name" : "ISR Imaging"
25 },
25 },
26 {
26 {
27 "code" : 120,
27 "code" : 120,
28 "name" : "Faraday"
28 "name" : "Faraday"
29 },
29 },
30 {
30 {
31 "code" : 121,
31 "code" : 121,
32 "name" : "Faraday Long Pulse"
32 "name" : "Faraday Long Pulse"
33 },
33 },
34 {
34 {
35 "code" : 122,
35 "code" : 122,
36 "name" : "Faraday Codded LP"
36 "name" : "Faraday Codded LP"
37 },
37 },
38 {
38 {
39 "code" : 123,
39 "code" : 123,
40 "name" : "Faraday Double Pulse"
40 "name" : "Faraday Double Pulse"
41 },
41 },
42 {
42 {
43 "code" : 124,
43 "code" : 124,
44 "name" : "Faraday AC"
44 "name" : "Faraday AC"
45 },
45 },
46 {
46 {
47 "code" : 125,
47 "code" : 125,
48 "name" : "Faraday Differential Phase"
48 "name" : "Faraday Differential Phase"
49 },
49 },
50 {
50 {
51 "code" : 130,
51 "code" : 130,
52 "name" : "Imaging"
52 "name" : "Imaging"
53 },
53 },
54 {
54 {
55 "code" : 132,
55 "code" : 132,
56 "name" : "Meteors"
56 "name" : "Meteors"
57 },
57 },
58 {
58 {
59 "code" : 150,
59 "code" : 150,
60 "name" : "JASMET 50"
60 "name" : "JASMET 50"
61 },
61 },
62 {
62 {
63 "code" : 151,
63 "code" : 151,
64 "name" : "JASMET 30"
64 "name" : "JASMET 30"
65 },
65 },
66 {
66 {
67 "code" : 170,
67 "code" : 170,
68 "name" : "BLTR Huancayo"
68 "name" : "BLTR Huancayo"
69 },
69 },
70 {
70 {
71 "code" : 171,
71 "code" : 171,
72 "name" : "CIRI Huancayo"
72 "name" : "CIRI Huancayo"
73 },
73 },
74 {
74 {
75 "code" : 172,
75 "code" : 172,
76 "name" : "CLAIRE Huancayo"
76 "name" : "CLAIRE Huancayo"
77 },
77 },
78 {
78 {
79 "code" : 180,
79 "code" : 180,
80 "name" : "MST"
80 "name" : "MST"
81 },
81 },
82 {
82 {
83 "code" : 181,
83 "code" : 181,
84 "name" : "ISR"
84 "name" : "ISR"
85 },
85 },
86 {
86 {
87 "code" : 182,
87 "code" : 182,
88 "name" : "EEJ"
88 "name" : "EEJ"
89 },
89 },
90 {
90 {
91 "code" : 190,
91 "code" : 190,
92 "name" : "JULIA 150Km (Natalia)"
92 "name" : "JULIA 150Km (Natalia)"
93 },
93 },
94 {
94 {
95 "code" : 191,
95 "code" : 191,
96 "name" : "JULIA SpreadF (Natalia)"
96 "name" : "JULIA SpreadF (Natalia)"
97 },
97 },
98 {
98 {
99 "code" : 200,
99 "code" : 200,
100 "name" : "JULIA 150Km"
100 "name" : "JULIA 150Km"
101 },
101 },
102 {
102 {
103 "code" : 201,
103 "code" : 201,
104 "name" : "JULIA EEJ"
104 "name" : "JULIA EEJ"
105 },
105 },
106 {
106 {
107 "code" : 202,
107 "code" : 202,
108 "name" : "JULIA SpreadF"
108 "name" : "JULIA SpreadF"
109 },
109 },
110 {
110 {
111 "code" : 203,
111 "code" : 203,
112 "name" : "JULIA Imaging"
112 "name" : "JULIA Imaging"
113 },
113 },
114 {
114 {
115 "code" : 204,
115 "code" : 204,
116 "name" : "JULIA Bistatic"
116 "name" : "JULIA Bistatic"
117 },
117 },
118 {
118 {
119 "code" : 210,
120 "name" : "High Altitude Drift"
121 },
122 {
119 "code" : 230,
123 "code" : 230,
120 "name" : "Valley Bottonside 150 Km"
124 "name" : "Valley Bottonside 150 Km"
121 },
125 },
122 {
126 {
123 "code" : 240,
127 "code" : 240,
124 "name" : "Simone Oyon"
128 "name" : "Simone Ancon"
125 },
129 },
126 {
130 {
127 "code" : 241,
131 "code" : 241,
128 "name" : "Simone Azpitia"
132 "name" : "Simone Azpitia"
129 },
133 },
130 {
134 {
131 "code" : 242,
135 "code" : 242,
132 "name" : "Simone Santa Rosa"
136 "name" : "Simone Santa Rosa"
133 },
137 },
134 {
138 {
135 "code" : 243,
139 "code" : 243,
136 "name" : "Simone Huancayo"
140 "name" : "Simone Huancayo"
137 },
141 },
138 {
142 {
139 "code" : 244,
143 "code" : 244,
140 "name" : "Simone Ancon"
144 "name" : "Simone Chaclacayo"
141 }
145 }
142 ]
146 ]
@@ -1,169 +1,172
1 #!/usr/bin/python
1 #!/usr/bin/python
2 # -*- coding: UTF-8 -*-
2 # -*- coding: UTF-8 -*-
3
3
4 import os
4 import os
5 import sys
5 import sys
6 import json
6 import json
7 import simplejson
7 import simplejson
8 from datetime import datetime
8 from datetime import datetime
9 import time
9 import time
10 import zmq
10 import zmq
11 import mongoengine
11 import mongoengine
12 import django
12 import django
13 from threading import Thread
13 from threading import Thread
14
14
15 sys.path.append(os.environ.get('APP_DIR', '../'))
15 sys.path.append(os.environ.get('APP_DIR', '../'))
16 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "realtime.settings")
16 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "realtime.settings")
17 django.setup()
17 django.setup()
18
18
19 from plotter.models import Experiment, ExpDetail, PlotMeta, PlotData
19 from plotter.models import Experiment, ExpDetail, PlotMeta, PlotData
20
20
21 host_mongo = os.environ.get('HOST_MONGO', 'localhost')
21 host_mongo = os.environ.get('HOST_MONGO', 'localhost')
22 mongoengine.connect('dbplots', host=host_mongo, port=27017)
22 mongoengine.connect('dbplots', host=host_mongo, port=27017)
23
23
24 import channels.layers
24 import channels.layers
25 from asgiref.sync import async_to_sync
25 from asgiref.sync import async_to_sync
26
26
27 channel = channels.layers.get_channel_layer()
27 channel = channels.layers.get_channel_layer()
28
28
29 def loaddata():
29 def loaddata():
30 print('Loading Experiments...')
30 print('Loading Experiments...')
31 if os.environ.get('APP_DIR', None) is not None:
31 if os.environ.get('APP_DIR', None) is not None:
32 file_exp = os.path.join(os.environ.get('APP_DIR'), 'scripts', 'experiments.json')
32 file_exp = os.path.join(os.environ.get('APP_DIR'), 'scripts', 'experiments.json')
33 else:
33 else:
34 file_exp = './experiments.json'
34 file_exp = './experiments.json'
35 for tup in json.load(open(file_exp)):
35 for tup in json.load(open(file_exp)):
36 print(tup)
36 print(tup)
37 exp = Experiment.objects(code=tup['code']).modify(
37 exp = Experiment.objects(code=tup['code']).modify(
38 upsert=True, # To add a new row
38 upsert=True, # To add a new row
39 new=True,
39 new=True,
40 set__code=tup['code'],
40 set__code=tup['code'],
41 set__name=tup['name'],
41 set__name=tup['name'],
42 )
42 )
43 exp.save()
43 exp.save()
44
44
45 #============== funcion para modificar datos en la tabla ==============
45 #============== funcion para modificar datos en la tabla ==============
46 def update(buffer):
46 def update(buffer):
47 dt = datetime.utcfromtimestamp(buffer['time'])
47 dt = datetime.fromtimestamp(buffer['time'])
48 interval = buffer['metadata'].pop('interval')
48 interval = buffer['metadata'].pop('interval')
49 tag = buffer['metadata'].pop('tag') if 'tag' in buffer['metadata'] else ''
49 tag = buffer['metadata'].pop('tag') if 'tag' in buffer['metadata'] else ''
50 exp = Experiment.objects.get(code=buffer['code'])
50 exp = Experiment.objects.get(code=buffer['code'])
51
51
52 detail = ExpDetail.objects(experiment=exp, date=dt.date()).modify(
52 detail = ExpDetail.objects(experiment=exp, date=dt.date()).modify(
53 upsert=True,
53 upsert=True,
54 new=True,
54 new=True,
55 set__experiment=exp,
55 set__experiment=exp,
56 set__date=dt.date(),
56 set__date=dt.date(),
57 set__last_time = buffer['time'],
57 set__last_time = buffer['time'],
58 set__interval = interval,
58 set__interval = interval,
59 set__tag = tag,
59 set__tag = tag,
60 )
60 )
61
61
62 label = buffer['plot'].replace(' ', '_').lower()
62 label = buffer['plot'].replace(' ', '_').lower()
63 plot = PlotMeta.objects(exp_detail=detail, plot=label).modify(
63 plot = PlotMeta.objects(exp_detail=detail, plot=label).modify(
64 upsert=True,
64 upsert=True,
65 new=True,
65 new=True,
66 set__metadata = buffer['metadata']
66 set__metadata = buffer['metadata']
67 )
67 )
68 #plot.save()
68 #plot.save()
69
69
70 data = PlotData.objects(plot=plot, time=buffer['time']).modify(
70 data = PlotData.objects(plot=plot, time=buffer['time']).modify(
71 upsert=True, # To add a new row
71 upsert=True, # To add a new row
72 new=True,
72 new=True,
73 set__time = buffer['time'],
73 set__time = buffer['time'],
74 set__data = buffer['data']
74 set__data = buffer['data']
75 )
75 )
76
76
77 #data.save()
77 #data.save()
78
78
79 if datetime.now().date() == dt.date():
79 if datetime.now().date() == dt.date():
80 return True
80 return True
81
81
82 return False
82 return False
83
83
84 # Function that is checking the state of my clients every 30s
84 # Function that is checking the state of my clients every 30s
85 def check_times():
85 def check_times():
86
86
87 while True:
87 while True:
88 dt = datetime.now()
88 dt = datetime.now()
89 exps = ExpDetail.objects(date=dt.date())
89 exps = ExpDetail.objects(date=dt.date())
90
90
91 for detail in exps:
91 for detail in exps:
92 code = detail.experiment.code
92 code = detail.experiment.code
93 plot = detail.plots()[0]
93 plot = detail.plots()[0]
94 t = time.time()
94 t = time.time()
95
95
96 message = {
96 message = {
97 'code': code,
97 'code': code,
98 'time': detail['last_time']
98 'time': detail['last_time']
99 }
99 }
100
100
101 if (t-detail['last_time']) > 6*detail['interval']:
101 if (t-detail['last_time']) > 6*detail['interval']:
102 value = 'danger'
102 value = 'danger'
103 elif (t-detail['last_time']) > 3*detail['interval']:
103 elif (t-detail['last_time']) > 3*detail['interval']:
104 value = 'warning'
104 value = 'warning'
105 else:
105 else:
106 value = 'success'
106 value = 'success'
107
107
108 print(('{} {} {} {} {}'.format(code, t, detail['last_time'], (t-detail['last_time']), value)))
108 print(('{} {} {} {} {}'.format(code, t, detail['last_time'], (t-detail['last_time']), value)))
109
109
110 message['value'] = value
110 message['value'] = value
111
111
112 async_to_sync(channel.group_send)(
112 async_to_sync(channel.group_send)(
113 'main',
113 'main',
114 {
114 {
115 'type': 'zmq_message',
115 'type': 'zmq_message',
116 'message': json.dumps(message)
116 'message': json.dumps(message)
117 }
117 }
118 )
118 )
119
119
120 time.sleep(60)
120 time.sleep(60)
121
121
122 def main():
122 def main():
123 print('Starting ZMQ server...')
123 print('Starting ZMQ server...')
124 context = zmq.Context()
124 context = zmq.Context()
125 receiver = context.socket(zmq.REP)
125 receiver = context.socket(zmq.REP)
126 receiver.bind("tcp://0.0.0.0:4444")
126 receiver.bind("tcp://0.0.0.0:4444")
127 t = Thread(target=check_times)
127 t = Thread(target=check_times)
128 t.start()
128 t.start()
129
129
130 while True:
130 while True:
131
131
132 buffer = receiver.recv_json()
132 try:
133 buffer = receiver.recv_json()
134 except:
135 continue
133 if not isinstance(buffer, dict):
136 if not isinstance(buffer, dict):
134 print('Invalid data received: {}').format(str(buffer))
137 print('Invalid data received: {}').format(str(buffer))
135 continue
138 continue
136
139
137 if not update(buffer):
140 if not update(buffer):
138 print('Updating {} for code {}'.format(
141 print('Updating {} for code {}'.format(
139 buffer['plot'],
142 buffer['plot'],
140 buffer['code']
143 buffer['code']
141 ))
144 ))
142 else:
145 else:
143 buffer['time'] = [buffer['time']]
146 buffer['time'] = [buffer['time']]
144 group = '{}_{}'.format(
147 group = '{}_{}'.format(
145 buffer['code'],
148 buffer['code'],
146 buffer['plot'].replace(' ', '_').lower()
149 buffer['plot'].replace(' ', '_').lower()
147 )
150 )
148 async_to_sync(channel.group_send)(
151 async_to_sync(channel.group_send)(
149 group,
152 group,
150 {
153 {
151 'type': 'zmq_message',
154 'type': 'zmq_message',
152 'message': simplejson.dumps(buffer, ignore_nan=True)
155 'message': simplejson.dumps(buffer, ignore_nan=True)
153 }
156 }
154 )
157 )
155
158
156 print('Sending to group {}_{} - {} bytes'.format(
159 print('Sending to group {}_{} - {} bytes'.format(
157 buffer['code'],
160 buffer['code'],
158 buffer['plot'].replace(' ', '_').lower(),
161 buffer['plot'].replace(' ', '_').lower(),
159 len(str(buffer)))
162 len(str(buffer)))
160 )
163 )
161
164
162 receiver.send_string('ok')
165 receiver.send_string('ok')
163
166
164 receiver.close()
167 receiver.close()
165 context.term()
168 context.term()
166
169
167 if __name__=='__main__':
170 if __name__=='__main__':
168 loaddata()
171 loaddata()
169 main()
172 main()
@@ -1,430 +1,430
1 """
1 """
2 The TIME_CONVERSIONS.py module gathers classes and functions for time system transformations
2 The TIME_CONVERSIONS.py module gathers classes and functions for time system transformations
3 (e.g. between seconds from 1970 to datetime format).
3 (e.g. between seconds from 1970 to datetime format).
4
4
5 MODULES CALLED:
5 MODULES CALLED:
6 NUMPY, TIME, DATETIME, CALENDAR
6 NUMPY, TIME, DATETIME, CALENDAR
7
7
8 MODIFICATION HISTORY:
8 MODIFICATION HISTORY:
9 Created by Ing. Freddy Galindo (frederickgalindo@gmail.com). ROJ Aug 13, 2009.
9 Created by Ing. Freddy Galindo (frederickgalindo@gmail.com). ROJ Aug 13, 2009.
10 """
10 """
11
11
12 import numpy
12 import numpy
13 import time
13 import time
14 from datetime import datetime as dt
14 from datetime import datetime as dt
15 import calendar
15 import calendar
16
16
17 class Time:
17 class Time:
18 """
18 """
19 time(year,month,dom,hour,min,secs)
19 time(year,month,dom,hour,min,secs)
20
20
21 An object represents a date and time of certain event..
21 An object represents a date and time of certain event..
22
22
23 Parameters
23 Parameters
24 ----------
24 ----------
25 YEAR = Number of the desired year. Year must be valid values from the civil calendar.
25 YEAR = Number of the desired year. Year must be valid values from the civil calendar.
26 Years B.C.E must be represented as negative integers. Years in the common era are repre-
26 Years B.C.E must be represented as negative integers. Years in the common era are repre-
27 sented as positive integers. In particular, note that there is no year 0 in the civil
27 sented as positive integers. In particular, note that there is no year 0 in the civil
28 calendar. 1 B.C.E. (-1) is followed by 1 C.E. (1).
28 calendar. 1 B.C.E. (-1) is followed by 1 C.E. (1).
29
29
30 MONTH = Number of desired month (1=Jan, ..., 12=December).
30 MONTH = Number of desired month (1=Jan, ..., 12=December).
31
31
32 DOM = Number of day of the month.
32 DOM = Number of day of the month.
33
33
34 HOUR = Number of the hour of the day. By default hour=0
34 HOUR = Number of the hour of the day. By default hour=0
35
35
36 MINS = Number of the minute of the hour. By default min=0
36 MINS = Number of the minute of the hour. By default min=0
37
37
38 SECS = Number of the second of the minute. By default secs=0.
38 SECS = Number of the second of the minute. By default secs=0.
39
39
40 Examples
40 Examples
41 --------
41 --------
42 time_info = time(2008,9,30,12,30,00)
42 time_info = time(2008,9,30,12,30,00)
43
43
44 time_info = time(2008,9,30)
44 time_info = time(2008,9,30)
45 """
45 """
46
46
47 def __init__(self, year=None, month=None, dom=None, hour=0, mins=0, secs=0):
47 def __init__(self, year=None, month=None, dom=None, hour=0, mins=0, secs=0):
48 # If one the first three inputs are not defined, it takes the current date.
48 # If one the first three inputs are not defined, it takes the current date.
49 date = time.localtime()
49 date = time.localtime()
50 if year==None:year=date[0]
50 if year==None:year=date[0]
51 if month==None:month=date[1]
51 if month==None:month=date[1]
52 if dom==None:dom=date[2]
52 if dom==None:dom=date[2]
53
53
54 # Converting to arrays
54 # Converting to arrays
55 year = numpy.array([year]); month = numpy.array([month]); dom = numpy.array([dom])
55 year = numpy.array([year]); month = numpy.array([month]); dom = numpy.array([dom])
56 hour = numpy.array([hour]); mins = numpy.array([mins]); secs = numpy.array([secs])
56 hour = numpy.array([hour]); mins = numpy.array([mins]); secs = numpy.array([secs])
57
57
58 # Defining time information object.
58 # Defining time information object.
59 self.year = numpy.atleast_1d(year)
59 self.year = numpy.atleast_1d(year)
60 self.month = numpy.atleast_1d(month)
60 self.month = numpy.atleast_1d(month)
61 self.dom = numpy.atleast_1d(dom)
61 self.dom = numpy.atleast_1d(dom)
62 self.hour = numpy.atleast_1d(hour)
62 self.hour = numpy.atleast_1d(hour)
63 self.mins = numpy.atleast_1d(mins)
63 self.mins = numpy.atleast_1d(mins)
64 self.secs = numpy.atleast_1d(secs)
64 self.secs = numpy.atleast_1d(secs)
65
65
66 def change2julday(self):
66 def change2julday(self):
67 """
67 """
68 Converts a datetime to Julian days.
68 Converts a datetime to Julian days.
69 """
69 """
70
70
71 # Defining constants
71 # Defining constants
72 greg = 2299171 # incorrect Julian day for Oct, 25, 1582.
72 greg = 2299171 # incorrect Julian day for Oct, 25, 1582.
73 min_calendar = -4716
73 min_calendar = -4716
74 max_calendar = 5000000
74 max_calendar = 5000000
75
75
76 min_year = numpy.nanmin(self.year)
76 min_year = numpy.nanmin(self.year)
77 max_year = numpy.nanmax(self.year)
77 max_year = numpy.nanmax(self.year)
78 if (min_year<min_calendar) or (max_year>max_calendar):
78 if (min_year<min_calendar) or (max_year>max_calendar):
79 print ("Value of Julian date is out of allowed range")
79 print ("Value of Julian date is out of allowed range")
80 return -1
80 return -1
81
81
82 noyear = numpy.sum(self.year==0)
82 noyear = numpy.sum(self.year==0)
83 if noyear>0:
83 if noyear>0:
84 print ("There is no year zero in the civil calendar")
84 print ("There is no year zero in the civil calendar")
85 return -1
85 return -1
86
86
87 # Knowing if the year is less than 0.
87 # Knowing if the year is less than 0.
88 bc = self.year<0
88 bc = self.year<0
89
89
90 # Knowing if the month is less than March.
90 # Knowing if the month is less than March.
91 inJanFeb = self.month<=2
91 inJanFeb = self.month<=2
92
92
93 jy = self.year + bc - inJanFeb
93 jy = self.year + bc - inJanFeb
94 jm = self.month + (1 + 12*inJanFeb)
94 jm = self.month + (1 + 12*inJanFeb)
95
95
96 # Computing Julian days.
96 # Computing Julian days.
97 jul= numpy.floor(365.25*jy) + numpy.floor(30.6001*jm) + (self.dom+1720995.0)
97 jul= numpy.floor(365.25*jy) + numpy.floor(30.6001*jm) + (self.dom+1720995.0)
98
98
99 # Test whether to change to Gregorian Calendar
99 # Test whether to change to Gregorian Calendar
100 if numpy.min(jul) >= greg:
100 if numpy.min(jul) >= greg:
101 ja = numpy.int32(0.01*jy)
101 ja = numpy.int32(0.01*jy)
102 jul = jul + 2 - ja + numpy.int32(0.25*ja)
102 jul = jul + 2 - ja + numpy.int32(0.25*ja)
103 else:
103 else:
104 gregchange = numpy.where(jul >= greg)
104 gregchange = numpy.where(jul >= greg)
105 if gregchange[0].size>0:
105 if gregchange[0].size>0:
106 ja = numpy.int32(0.01 + jy[gregchange])
106 ja = numpy.int32(0.01 + jy[gregchange])
107 jy[gregchange] = jy[gregchange] + 2 - ja + numpy.int32(0.25*ja)
107 jy[gregchange] = jy[gregchange] + 2 - ja + numpy.int32(0.25*ja)
108
108
109 # Determining machine-specific parameters affecting floating-point.
109 # Determining machine-specific parameters affecting floating-point.
110 eps = 0.0 # Replace this line for a function to get precision.
110 eps = 0.0 # Replace this line for a function to get precision.
111 eps = abs(jul)*0.0 > eps
111 eps = abs(jul)*0.0 > eps
112
112
113 jul = jul + (self.hour/24. -0.5) + (self.mins/1440.) + (self.secs/86400.) + eps
113 jul = jul + (self.hour/24. -0.5) + (self.mins/1440.) + (self.secs/86400.) + eps
114
114
115 return jul[0]
115 return jul[0]
116
116
117 def change2secs(self):
117 def change2secs(self):
118 """
118 """
119 Converts datetime to number of seconds respect to 1970.
119 Converts datetime to number of seconds respect to 1970.
120 """
120 """
121
121
122 dtime = dt(self.year, self.month, self.dom)
122 dtime = dt(self.year[0], self.month[0], self.dom[0])
123 return (dtime-dt(1970, 1, 1)).total_seconds()
123 return (dtime-dt(1970, 1, 1)).total_seconds()
124
124
125 year = self.year
125 year = self.year
126 if year.size>1: year = year[0]
126 if year.size>1: year = year[0]
127
127
128 month = self.month
128 month = self.month
129 if month.size>1: month = month[0]
129 if month.size>1: month = month[0]
130
130
131 dom = self.dom
131 dom = self.dom
132 if dom.size>1: dom = dom[0]
132 if dom.size>1: dom = dom[0]
133
133
134 # Resizing hour, mins and secs if it was necessary.
134 # Resizing hour, mins and secs if it was necessary.
135 hour = self.hour
135 hour = self.hour
136 if hour.size>1:hour = hour[0]
136 if hour.size>1:hour = hour[0]
137 if hour.size==1:hour = numpy.resize(hour,year.size)
137 if hour.size==1:hour = numpy.resize(hour,year.size)
138
138
139 mins = self.mins
139 mins = self.mins
140 if mins.size>1:mins = mins[0]
140 if mins.size>1:mins = mins[0]
141 if mins.size==1:mins = numpy.resize(mins,year.size)
141 if mins.size==1:mins = numpy.resize(mins,year.size)
142
142
143 secs = self.secs
143 secs = self.secs
144 if secs.size>1:secs = secs[0]
144 if secs.size>1:secs = secs[0]
145 if secs.size==1:secs = numpy.resize(secs,year.size)
145 if secs.size==1:secs = numpy.resize(secs,year.size)
146
146
147 # Using time.mktime to compute seconds respect to 1970.
147 # Using time.mktime to compute seconds respect to 1970.
148 secs1970 = numpy.zeros(year.size)
148 secs1970 = numpy.zeros(year.size)
149 for ii in numpy.arange(year.size):
149 for ii in numpy.arange(year.size):
150 secs1970[ii] = time.mktime((int(year[ii]),int(month[ii]),int(dom[ii]),\
150 secs1970[ii] = time.mktime((int(year[ii]),int(month[ii]),int(dom[ii]),\
151 int(hour[ii]),int(mins[ii]),int(secs[ii]),0,0,0))
151 int(hour[ii]),int(mins[ii]),int(secs[ii]),0,0,0))
152
152
153 secs1970 = numpy.int32(secs1970 - time.timezone)
153 secs1970 = numpy.int32(secs1970 - time.timezone)
154
154
155 return secs1970
155 return secs1970
156
156
157 def change2strdate(self,mode=1):
157 def change2strdate(self,mode=1):
158 """
158 """
159 change2strdate method converts a date and time of certain event to date string. The
159 change2strdate method converts a date and time of certain event to date string. The
160 string format is like localtime (e.g. Fri Oct 9 15:00:19 2009).
160 string format is like localtime (e.g. Fri Oct 9 15:00:19 2009).
161
161
162 Parameters
162 Parameters
163 ----------
163 ----------
164 None.
164 None.
165
165
166 Return
166 Return
167 ------
167 ------
168
168
169 Modification History
169 Modification History
170 --------------------
170 --------------------
171 Created by Freddy R. Galindo, ROJ, 09 October 2009.
171 Created by Freddy R. Galindo, ROJ, 09 October 2009.
172
172
173 """
173 """
174
174
175 secs = numpy.atleast_1d(self.change2secs())
175 secs = numpy.atleast_1d(self.change2secs())
176 strdate = []
176 strdate = []
177 for ii in numpy.arange(numpy.size(secs)):
177 for ii in numpy.arange(numpy.size(secs)):
178 secs_tmp = time.localtime(secs[ii] + time.timezone)
178 secs_tmp = time.localtime(secs[ii] + time.timezone)
179 if mode==1:
179 if mode==1:
180 strdate.append(time.strftime("%d-%b-%Y (%j) %H:%M:%S",secs_tmp))
180 strdate.append(time.strftime("%d-%b-%Y (%j) %H:%M:%S",secs_tmp))
181 elif mode==2:
181 elif mode==2:
182 strdate.append(time.strftime("%d-%b-%Y (%j)",secs_tmp))
182 strdate.append(time.strftime("%d-%b-%Y (%j)",secs_tmp))
183
183
184 strdate = numpy.array(strdate)
184 strdate = numpy.array(strdate)
185
185
186 return strdate
186 return strdate
187
187
188
188
189 class Secs:
189 class Secs:
190 """
190 """
191 secs(secs):
191 secs(secs):
192
192
193 An object represents the number of seconds respect to 1970.
193 An object represents the number of seconds respect to 1970.
194
194
195 Parameters
195 Parameters
196 ----------
196 ----------
197
197
198 SECS = A scalar or array giving the number of seconds respect to 1970.
198 SECS = A scalar or array giving the number of seconds respect to 1970.
199
199
200 Example:
200 Example:
201 --------
201 --------
202 secs_info = secs(1251241373)
202 secs_info = secs(1251241373)
203
203
204 secs_info = secs([1251241373,1251241383,1251241393])
204 secs_info = secs([1251241373,1251241383,1251241393])
205 """
205 """
206 def __init__(self,secs):
206 def __init__(self,secs):
207 self.secs = secs
207 self.secs = secs
208
208
209 def change2julday(self):
209 def change2julday(self):
210 """
210 """
211 Convert seconds from 1970 to Julian days.
211 Convert seconds from 1970 to Julian days.
212 """
212 """
213
213
214 secs_1970 = time(1970,1,1,0,0,0).change2julday()
214 secs_1970 = time(1970,1,1,0,0,0).change2julday()
215
215
216 julian = self.secs/86400.0 + secs_1970
216 julian = self.secs/86400.0 + secs_1970
217
217
218 return julian
218 return julian
219
219
220 def change2time(self):
220 def change2time(self):
221 """
221 """
222 Converts seconds from 1970 to datetime.
222 Converts seconds from 1970 to datetime.
223 """
223 """
224
224
225 secs1970 = numpy.atleast_1d(self.secs)
225 secs1970 = numpy.atleast_1d(self.secs)
226
226
227 datetime = numpy.zeros((9,secs1970.size))
227 datetime = numpy.zeros((9,secs1970.size))
228 for ii in numpy.arange(secs1970.size):
228 for ii in numpy.arange(secs1970.size):
229 tuple = time.gmtime(secs1970[ii])
229 tuple = time.gmtime(secs1970[ii])
230 datetime[0,ii] = tuple[0]
230 datetime[0,ii] = tuple[0]
231 datetime[1,ii] = tuple[1]
231 datetime[1,ii] = tuple[1]
232 datetime[2,ii] = tuple[2]
232 datetime[2,ii] = tuple[2]
233 datetime[3,ii] = tuple[3]
233 datetime[3,ii] = tuple[3]
234 datetime[4,ii] = tuple[4]
234 datetime[4,ii] = tuple[4]
235 datetime[5,ii] = tuple[5]
235 datetime[5,ii] = tuple[5]
236 datetime[6,ii] = tuple[6]
236 datetime[6,ii] = tuple[6]
237 datetime[7,ii] = tuple[7]
237 datetime[7,ii] = tuple[7]
238 datetime[8,ii] = tuple[8]
238 datetime[8,ii] = tuple[8]
239
239
240 datetime = numpy.int32(datetime)
240 datetime = numpy.int32(datetime)
241
241
242 return datetime
242 return datetime
243
243
244
244
245 class Julian:
245 class Julian:
246 """
246 """
247 julian(julian):
247 julian(julian):
248
248
249 An object represents julian days.
249 An object represents julian days.
250
250
251 Parameters
251 Parameters
252 ----------
252 ----------
253
253
254 JULIAN = A scalar or array giving the julina days.
254 JULIAN = A scalar or array giving the julina days.
255
255
256 Example:
256 Example:
257 --------
257 --------
258 julian_info = julian(2454740)
258 julian_info = julian(2454740)
259
259
260 julian_info = julian([2454740,2454760,2454780])
260 julian_info = julian([2454740,2454760,2454780])
261 """
261 """
262 def __init__(self,julian):
262 def __init__(self,julian):
263 self.julian = numpy.atleast_1d(julian)
263 self.julian = numpy.atleast_1d(julian)
264
264
265 def change2time(self):
265 def change2time(self):
266 """
266 """
267 change2time method converts from julian day to calendar date and time.
267 change2time method converts from julian day to calendar date and time.
268
268
269 Return
269 Return
270 ------
270 ------
271 year = An array giving the year of the desired julian day.
271 year = An array giving the year of the desired julian day.
272 month = An array giving the month of the desired julian day.
272 month = An array giving the month of the desired julian day.
273 dom = An array giving the day of the desired julian day.
273 dom = An array giving the day of the desired julian day.
274 hour = An array giving the hour of the desired julian day.
274 hour = An array giving the hour of the desired julian day.
275 mins = An array giving the minute of the desired julian day.
275 mins = An array giving the minute of the desired julian day.
276 secs = An array giving the second of the desired julian day.
276 secs = An array giving the second of the desired julian day.
277
277
278 Examples
278 Examples
279 --------
279 --------
280 >> jd = 2455119.0
280 >> jd = 2455119.0
281 >> [yy,mo,dd,hh,mi,ss] = TimeTools.julian(jd).change2time()
281 >> [yy,mo,dd,hh,mi,ss] = TimeTools.julian(jd).change2time()
282 >> print [yy,mo,dd,hh,mi,ss]
282 >> print [yy,mo,dd,hh,mi,ss]
283 [2009] [10] [ 14.] [ 12.] [ 0.] [ 0.]
283 [2009] [10] [ 14.] [ 12.] [ 0.] [ 0.]
284
284
285 Modification history
285 Modification history
286 --------------------
286 --------------------
287 Translated from "Numerical Recipies in C", by William H. Press, Brian P. Flannery,
287 Translated from "Numerical Recipies in C", by William H. Press, Brian P. Flannery,
288 Saul A. Teukolsky, and William T. Vetterling. Cambridge University Press, 1988.
288 Saul A. Teukolsky, and William T. Vetterling. Cambridge University Press, 1988.
289 Converted to Python by Freddy R. Galindo, ROJ, 06 October 2009.
289 Converted to Python by Freddy R. Galindo, ROJ, 06 October 2009.
290 """
290 """
291
291
292 min_julian = -1095
292 min_julian = -1095
293 max_julian = 1827933925
293 max_julian = 1827933925
294 if (numpy.min(self.julian) < min_julian) or (numpy.max(self.julian) > max_julian):
294 if (numpy.min(self.julian) < min_julian) or (numpy.max(self.julian) > max_julian):
295 print ('Value of Julian date is out of allowed range.')
295 print ('Value of Julian date is out of allowed range.')
296 return None
296 return None
297
297
298 # Beginning of Gregorian calendar
298 # Beginning of Gregorian calendar
299 igreg = 2299161
299 igreg = 2299161
300 julLong = numpy.floor(self.julian + 0.5)
300 julLong = numpy.floor(self.julian + 0.5)
301 minJul = numpy.min(julLong)
301 minJul = numpy.min(julLong)
302
302
303 if (minJul >= igreg):
303 if (minJul >= igreg):
304 # All are Gregorian
304 # All are Gregorian
305 jalpha = numpy.int32(((julLong - 1867216) - 0.25)/36524.25)
305 jalpha = numpy.int32(((julLong - 1867216) - 0.25)/36524.25)
306 ja = julLong + 1 + jalpha - numpy.int32(0.25*jalpha)
306 ja = julLong + 1 + jalpha - numpy.int32(0.25*jalpha)
307 else:
307 else:
308 ja = julLong
308 ja = julLong
309 gregChange = numpy.where(julLong >= igreg)
309 gregChange = numpy.where(julLong >= igreg)
310 if gregChange[0].size>0:
310 if gregChange[0].size>0:
311 jalpha = numpy.int32(((julLong[gregChange]-1867216) - 0.25)/36524.25)
311 jalpha = numpy.int32(((julLong[gregChange]-1867216) - 0.25)/36524.25)
312 ja[gregChange] = julLong[gregChange]+1+jalpha-numpy.int32(0.25*jalpha)
312 ja[gregChange] = julLong[gregChange]+1+jalpha-numpy.int32(0.25*jalpha)
313
313
314 # clear memory.
314 # clear memory.
315 jalpha = -1
315 jalpha = -1
316
316
317 jb = ja + 1524
317 jb = ja + 1524
318 jc = numpy.int32(6680. + ((jb-2439870)-122.1)/365.25)
318 jc = numpy.int32(6680. + ((jb-2439870)-122.1)/365.25)
319 jd = numpy.int32(365.*jc + (0.25*jc))
319 jd = numpy.int32(365.*jc + (0.25*jc))
320 je = numpy.int32((jb - jd)/30.6001)
320 je = numpy.int32((jb - jd)/30.6001)
321
321
322 dom = jb - jd - numpy.int32(30.6001*je)
322 dom = jb - jd - numpy.int32(30.6001*je)
323 month = je - 1
323 month = je - 1
324 month = ((month - 1) % 12) + 1
324 month = ((month - 1) % 12) + 1
325 month = numpy.atleast_1d(month)
325 month = numpy.atleast_1d(month)
326 year = jc - 4715
326 year = jc - 4715
327 year = year - (month > 2)*1
327 year = year - (month > 2)*1
328 year = year - (year <= 0)*1
328 year = year - (year <= 0)*1
329 year = numpy.atleast_1d(year)
329 year = numpy.atleast_1d(year)
330
330
331 # Getting hours, minutes, seconds
331 # Getting hours, minutes, seconds
332 fraction = self.julian + 0.5 - julLong
332 fraction = self.julian + 0.5 - julLong
333 eps_0 = dom*0.0 + 1.0e-12
333 eps_0 = dom*0.0 + 1.0e-12
334 eps_1 = 1.0e-12*numpy.abs(julLong)
334 eps_1 = 1.0e-12*numpy.abs(julLong)
335 eps = (eps_0>eps_1)*eps_0 + (eps_0<=eps_1)*eps_1
335 eps = (eps_0>eps_1)*eps_0 + (eps_0<=eps_1)*eps_1
336
336
337 hour_0 = dom*0 + 23
337 hour_0 = dom*0 + 23
338 hour_2 = dom*0 + 0
338 hour_2 = dom*0 + 0
339 hour_1 = numpy.floor(fraction*24.0 + eps)
339 hour_1 = numpy.floor(fraction*24.0 + eps)
340 hour = ((hour_1>hour_0)*23) + ((hour_1<=hour_0)*hour_1)
340 hour = ((hour_1>hour_0)*23) + ((hour_1<=hour_0)*hour_1)
341 hour = ((hour_1<hour_2)*0) + ((hour_1>=hour_2)*hour_1)
341 hour = ((hour_1<hour_2)*0) + ((hour_1>=hour_2)*hour_1)
342
342
343 fraction = fraction - (hour/24.0)
343 fraction = fraction - (hour/24.0)
344 mins_0 = dom*0 + 59
344 mins_0 = dom*0 + 59
345 mins_2 = dom*0 + 0
345 mins_2 = dom*0 + 0
346 mins_1 = numpy.floor(fraction*1440.0 + eps)
346 mins_1 = numpy.floor(fraction*1440.0 + eps)
347 mins = ((mins_1>mins_0)*59) + ((mins_1<=mins_0)*mins_1)
347 mins = ((mins_1>mins_0)*59) + ((mins_1<=mins_0)*mins_1)
348 mins = ((mins_1<mins_2)*0) + ((mins_1>=mins_2)*mins_1)
348 mins = ((mins_1<mins_2)*0) + ((mins_1>=mins_2)*mins_1)
349
349
350 secs_2 = dom*0 + 0
350 secs_2 = dom*0 + 0
351 secs_1 = (fraction - mins/1440.0)*86400.0
351 secs_1 = (fraction - mins/1440.0)*86400.0
352 secs = ((secs_1<secs_2)*0) + ((secs_1>=secs_2)*secs_1)
352 secs = ((secs_1<secs_2)*0) + ((secs_1>=secs_2)*secs_1)
353
353
354 return year,month,dom,hour,mins,secs
354 return year,month,dom,hour,mins,secs
355
355
356 def change2secs(self):
356 def change2secs(self):
357 """
357 """
358 Converts from Julian days to seconds from 1970.
358 Converts from Julian days to seconds from 1970.
359 """
359 """
360
360
361 jul_1970 = Time(1970,1,1,0,0,0).change2julday()
361 jul_1970 = Time(1970,1,1,0,0,0).change2julday()
362
362
363 secs = numpy.int32((self.julian - jul_1970)*86400)
363 secs = numpy.int32((self.julian - jul_1970)*86400)
364
364
365 return secs
365 return secs
366
366
367 def change2lst(self,longitude=-76.8667):
367 def change2lst(self,longitude=-76.8667):
368 """
368 """
369 CT2LST converts from local civil time to local mean sideral time
369 CT2LST converts from local civil time to local mean sideral time
370
370
371 longitude = The longitude in degrees (east of Greenwich) of the place for which
371 longitude = The longitude in degrees (east of Greenwich) of the place for which
372 the local sideral time is desired, scalar. The Greenwich mean sideral time (GMST)
372 the local sideral time is desired, scalar. The Greenwich mean sideral time (GMST)
373 can be found by setting longitude=0.
373 can be found by setting longitude=0.
374 """
374 """
375
375
376 # Useful constants, see Meus, p. 84
376 # Useful constants, see Meus, p. 84
377 c = numpy.array([280.46061837, 360.98564736629, 0.000387933, 38710000.0])
377 c = numpy.array([280.46061837, 360.98564736629, 0.000387933, 38710000.0])
378 jd2000 = 2451545.0
378 jd2000 = 2451545.0
379 t0 = self.julian - jd2000
379 t0 = self.julian - jd2000
380 t = t0/36525.
380 t = t0/36525.
381
381
382 # Computing GST in seconds
382 # Computing GST in seconds
383 theta = c[0] + (c[1]*t0) + (t**2)*(c[2]-t/c[3])
383 theta = c[0] + (c[1]*t0) + (t**2)*(c[2]-t/c[3])
384
384
385 # Computing LST in hours
385 # Computing LST in hours
386 lst = (theta + longitude)/15.0
386 lst = (theta + longitude)/15.0
387 neg = numpy.where(lst < 0.0)
387 neg = numpy.where(lst < 0.0)
388 if neg[0].size>0:lst[neg] = 24.0 + (lst[neg] % 24)
388 if neg[0].size>0:lst[neg] = 24.0 + (lst[neg] % 24)
389 lst = lst % 24.0
389 lst = lst % 24.0
390
390
391 return lst
391 return lst
392
392
393
393
394 class date2doy:
394 class date2doy:
395 def __init__(self,year,month,day):
395 def __init__(self,year,month,day):
396 self.year = year
396 self.year = year
397 self.month = month
397 self.month = month
398 self.day = day
398 self.day = day
399
399
400 def change2doy(self):
400 def change2doy(self):
401 if calendar.isleap(self.year) == True:
401 if calendar.isleap(self.year) == True:
402 tfactor = 1
402 tfactor = 1
403 else:
403 else:
404 tfactor = 2
404 tfactor = 2
405
405
406 day = self.day
406 day = self.day
407 month = self.month
407 month = self.month
408
408
409 doy = numpy.floor((275*month)/9.0) - (tfactor*numpy.floor((month+9)/12.0)) + day - 30
409 doy = numpy.floor((275*month)/9.0) - (tfactor*numpy.floor((month+9)/12.0)) + day - 30
410
410
411 return numpy.int32(doy)
411 return numpy.int32(doy)
412
412
413
413
414 class Doy2Date:
414 class Doy2Date:
415 def __init__(self,year,doy):
415 def __init__(self,year,doy):
416 self.year = year
416 self.year = year
417 self.doy = doy
417 self.doy = doy
418
418
419 def change2date(self):
419 def change2date(self):
420 months = numpy.arange(12) + 1
420 months = numpy.arange(12) + 1
421
421
422 first_dem = date2doy(self.year,months,1)
422 first_dem = date2doy(self.year,months,1)
423 first_dem = first_dem.change2doy()
423 first_dem = first_dem.change2doy()
424
424
425 imm = numpy.where((self.doy - first_dem) > 0)
425 imm = numpy.where((self.doy - first_dem) > 0)
426
426
427 month = imm[0].size
427 month = imm[0].size
428 dom = self.doy -first_dem[month - 1] + 1
428 dom = self.doy -first_dem[month - 1] + 1
429
429
430 return month, dom
430 return month, dom
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now