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