Commit 0740e23f authored by I.K Seneviratne's avatar I.K Seneviratne

Merge remote-tracking branch 'origin/QA_RELEASE' into monitoring_student_behavior

parents de499ad3 efa7d37c
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="canvasjs" level="application" />
</component> </component>
<component name="TemplatesService"> <component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" /> <option name="TEMPLATE_CONFIGURATION" value="Django" />
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{canvasjs}" />
</component>
</project>
\ No newline at end of file
# Generated by Django 3.0.3 on 2020-03-04 11:15 # Generated by Django 2.2.11 on 2020-09-07 07:56
import FirstApp.MongoModels
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
import djongo.models.fields
class Migration(migrations.Migration): class Migration(migrations.Migration):
...@@ -11,6 +14,44 @@ class Migration(migrations.Migration): ...@@ -11,6 +14,44 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.CreateModel(
name='Faculty',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('faculty_id', models.CharField(max_length=10)),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Lecture',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_created=True, default=None)),
('lecture_id', models.CharField(max_length=10)),
],
),
migrations.CreateModel(
name='Lecturer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecturer_id', models.CharField(max_length=7)),
('fname', models.TextField()),
('lname', models.TextField()),
('email', models.EmailField(max_length=254)),
('telephone', models.CharField(max_length=10)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.CreateModel(
name='RegisterUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('firstName', models.CharField(max_length=20)),
('lastName', models.CharField(max_length=30)),
('email', models.CharField(max_length=30)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel( migrations.CreateModel(
name='Teachers', name='Teachers',
fields=[ fields=[
...@@ -20,4 +61,116 @@ class Migration(migrations.Migration): ...@@ -20,4 +61,116 @@ class Migration(migrations.Migration):
('age', models.IntegerField()), ('age', models.IntegerField()),
], ],
), ),
migrations.CreateModel(
name='Video',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('path', models.CharField(max_length=100)),
('duration', models.CharField(max_length=100)),
('hours', models.IntegerField()),
('minutes', models.IntegerField()),
('seconds', models.IntegerField()),
],
),
migrations.CreateModel(
name='VideoMeta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fps', models.IntegerField()),
('frame_count', models.IntegerField()),
('happy_count', models.IntegerField()),
('sad_count', models.IntegerField()),
('angry_count', models.IntegerField()),
('neutral_count', models.IntegerField()),
('surprise_count', models.IntegerField()),
('happy_perct', models.IntegerField()),
('sad_perct', models.IntegerField()),
('angry_perct', models.IntegerField()),
('neutral_perct', models.IntegerField()),
('surprise_perct', models.IntegerField()),
],
),
migrations.CreateModel(
name='Subject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject_code', models.TextField()),
('name', models.TextField()),
('year', models.IntegerField()),
('faculty', models.ForeignKey(default={}, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.CreateModel(
name='LectureVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_video_id', models.CharField(max_length=10)),
('date', models.DateField()),
('video_name', models.CharField(max_length=50)),
('video_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LecturerSubject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lec_subject_id', models.CharField(max_length=10)),
('lecturer_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subjects', models.ManyToManyField(to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LecturerCredentials',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=15)),
('username', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
],
),
migrations.CreateModel(
name='LecturePoseEstimation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_pose_id', models.CharField(max_length=10)),
('lecture_video_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='LectureEmotionReport',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_emotion_id', models.CharField(max_length=10)),
('happy_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('sad_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('angry_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('disgust_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('surprise_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('neutral_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('lecture_video_id', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='LectureActivity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_activity_id', models.CharField(max_length=10)),
('talking_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('listening_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('writing_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('phone_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('lecture_video_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='FacultyTimetable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timetable_id', models.CharField(max_length=10)),
('timetable', djongo.models.fields.ArrayField(model_container=FirstApp.MongoModels.DateTimeTable)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
] ]
# Generated by Django 2.2.11 on 2020-03-16 12:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='RegisterUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('firstName', models.CharField(max_length=20)),
('lastName', models.CharField(max_length=30)),
('email', models.CharField(max_length=30)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='Video',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('path', models.CharField(max_length=100)),
('duration', models.CharField(max_length=100)),
('hours', models.IntegerField()),
('minutes', models.IntegerField()),
('seconds', models.IntegerField()),
],
),
migrations.CreateModel(
name='VideoMeta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fps', models.IntegerField()),
('frame_count', models.IntegerField()),
('happy_count', models.IntegerField()),
('sad_count', models.IntegerField()),
('angry_count', models.IntegerField()),
('neutral_count', models.IntegerField()),
('surprise_count', models.IntegerField()),
('happy_perct', models.IntegerField()),
('sad_perct', models.IntegerField()),
('angry_perct', models.IntegerField()),
('neutral_perct', models.IntegerField()),
('surprise_perct', models.IntegerField()),
],
),
]
# Generated by Django 2.2.11 on 2020-05-10 15:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0002_registeruser_video_videometa'),
]
operations = [
migrations.CreateModel(
name='LectureEmotionReport',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_id', models.CharField(max_length=10)),
('happy_perct', models.FloatField()),
('sad_perct', models.FloatField()),
('angry_perct', models.FloatField()),
('surprise_perct', models.FloatField()),
('disgust_perct', models.FloatField()),
('neutral_perct', models.FloatField()),
],
),
]
# Generated by Django 2.2.11 on 2020-05-11 16:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0003_lectureemotionreport'),
]
operations = [
migrations.CreateModel(
name='Lecture',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_created=True)),
('lecture_id', models.CharField(max_length=10)),
],
),
]
# Generated by Django 2.2.11 on 2020-05-13 10:21
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0004_lecture'),
]
operations = [
migrations.CreateModel(
name='Faculty',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('faculty_id', models.CharField(max_length=10)),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Lecturer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecturer_id', models.CharField(max_length=7)),
('fname', models.TextField()),
('lname', models.TextField()),
('email', models.EmailField(max_length=254)),
('telephone', models.CharField(max_length=10)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.AlterField(
model_name='lecture',
name='date',
field=models.DateTimeField(auto_created=True, default=None),
),
migrations.CreateModel(
name='Subject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject_code', models.TextField()),
('name', models.TextField()),
('year', models.IntegerField()),
('faculty', models.ForeignKey(default={}, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.CreateModel(
name='LecturerSubject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lec_subject_id', models.CharField(max_length=10)),
('lecturer_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subjects', models.ManyToManyField(to='FirstApp.Subject')),
],
),
]
# Generated by Django 2.2.11 on 2020-05-13 15:46
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0005_auto_20200513_1551'),
]
operations = [
migrations.CreateModel(
name='LecturerCredentials',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=15)),
('username', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
],
),
]
from django.contrib import admin from django.contrib import admin
# Register your models here. # Register your models here.
from LectureSummarizingApp.models import *
admin.site.register(LectureAudio)
admin.site.register(LectureAudioSummary)
from rest_framework.views import APIView
from rest_framework.response import Response
from LectureSummarizingApp.models import LectureAudio
from LectureSummarizingApp.serializer import LectureAudioSerializer
# this API will retrieve lecture audio details
class LectureAudioAPI(APIView):
def get(self, request):
lecture_audio = LectureAudio.objects.all()
lecture_audio_serializer = LectureAudioSerializer(lecture_audio, many=True)
data = lecture_audio_serializer.data
return Response({
"response": data
})
\ No newline at end of file
from django.apps import AppConfig from django.apps import AppConfig
class LecturesummarizingappConfig(AppConfig): class LectureSummarizingAppConfig(AppConfig):
name = 'LectureSummarizingApp' name = 'LectureSummarizingApp'
# Generated by Django 2.2.11 on 2020-09-15 07:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('FirstApp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='LectureAudio',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_audio_id', models.CharField(max_length=10)),
('lecturer_date', models.DateField()),
('lecture_audio_name', models.CharField(max_length=50)),
('lecture_audio_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LectureAudioSummary',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_audio_summary_id', models.CharField(max_length=10)),
('audio_original_text', models.TextField()),
('audio_summary', models.TextField()),
('lecture_audio_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='LectureSummarizingApp.LectureAudio')),
],
),
]
from django.db import models # from django.db import models
from djongo import models
# Create your models here. # Create your models here.
from FirstApp.MongoModels import Lecturer, Subject
class LectureAudio (models.Model):
lecture_audio_id = models.CharField(max_length=10)
lecturer_date = models.DateField()
lecture_audio_name = models.CharField(max_length=50)
lecture_audio_length = models.DurationField()
lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.lecture_audio_id
class LectureAudioSummary (models.Model):
lecture_audio_summary_id = models.CharField(max_length=10)
lecture_audio_id = models.ForeignKey(LectureAudio, on_delete=models.CASCADE)
audio_original_text = models.TextField()
audio_summary = models.TextField()
def __str__(self):
return self.lecture_audio_summary_id
from rest_framework import serializers
from FirstApp.serializers import LecturerSerializer, SubjectSerializer
from . models import *
class LectureAudioSerializer(serializers.ModelSerializer):
lecturer = LecturerSerializer()
subject = SubjectSerializer()
class Meta:
model = LectureAudio
fields = '__all__'
class LectureAudioSummarySerializer(serializers.ModelSerializer):
lecture_audio_id = LectureAudioSerializer()
class Meta:
model = LectureAudioSummary
fields = '__all__'
\ No newline at end of file
from django.urls import path, re_path, include
from . import views
from rest_framework import routers
from django.conf.urls import url
from . import api
router = routers.DefaultRouter()
# router.register(r'^register', views.register)
urlpatterns = [
# path('', views.hello),
# path('login', views.login),
# path('register', views.register),
# path('404', views.view404),
# path('blank', views.blank),
# path('buttons', views.buttons),
# path('cards', views.cards),
# path('charts', views.charts),
# path('forgot-password', views.forget_password),
# # path('webcam', views.webcam),
# path('template', views.template),
# path('base', views.base),
# path('child', views.child),
# path('lecture-video', views.lecVideo),
# # path('Video', views.hello)
# API to retrieve activity recognition
url(r'^get-lecture-audio/$', api.LectureAudioAPI.as_view()),
# # API to retrieve audio analysis
# url(r'^get-audio-analysis', api.GetLectureAudioAnalysis.as_view()),
#
# # API to retrieve lecture audio text
# url(r'^get-lecture-audio-text', api.LectureAudioTextAPI.as_view()),
#
# # test API
# url(r'^test-api', api.TestAPI.as_view()),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
from django.contrib import admin from django.contrib import admin
from . models import RegisterTeacher from .models import *
# Register your models here. # Register your models here.
admin.site.register(RegisterTeacher) admin.site.register(LecturerVideo)
\ No newline at end of file admin.site.register(LecturerAudioText)
admin.site.register(LecturerVideoMetaData)
admin.site.register(LectureRecordedVideo)
\ No newline at end of file
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from LectureSummarizingApp.models import LectureAudioSummary
from LectureSummarizingApp.serializer import LectureAudioSummarySerializer
from . logic import classroom_activity, text_analysis as ta from . logic import classroom_activity, text_analysis as ta
from .models import LecturerVideo, LecturerAudioText
from .serializers import LecturerVideoSerializer, LecturerAudioTextSerializer
import datetime
class ActivityRecognitionAPI(APIView): class ActivityRecognitionAPI(APIView):
...@@ -14,12 +21,139 @@ class ActivityRecognitionAPI(APIView): ...@@ -14,12 +21,139 @@ class ActivityRecognitionAPI(APIView):
pass pass
# class ActivityRecognitionAPI(APIView):
#
# def get(self, request):
# video_name = request.query_params.get('video_name')
# percentages = classroom_activity.activity_recognition(video_name)
# return Response({"response": percentages})
#
# def post(self, request):
# pass
# this class will be used to retrieve audio analysis for a lecture # this class will be used to retrieve audio analysis for a lecture
class GetLectureAudioAnalysis(APIView): class GetLectureAudioAnalysis(APIView):
def get(self, request): def get(self, request):
analysis = ta.run() lec_audio_id = request.query_params.get("audio_id")
int_audio_id = int(lec_audio_id)
lec_audio_summary = LectureAudioSummary.objects.filter(lecture_audio_id=int_audio_id)
lec_audio_summary_serializer = LectureAudioSummarySerializer(lec_audio_summary, many=True)
audio_summary_data = lec_audio_summary_serializer.data
lec_audio_summary_id = 0
for audio in audio_summary_data:
lec_audio_summary_id = audio['id']
# retrieve summary text data
lec_audio_text = LecturerAudioText.objects.filter(lecturer_audio_original_text__id=lec_audio_summary_id)
lec_audio_text_serializer = LecturerAudioTextSerializer(lec_audio_text, many=True)
lec_audio_text_data = lec_audio_text_serializer.data
audio_text = []
if len(lec_audio_text_data) > 0:
audio_text = lec_audio_text_data[0]
print('audio text: ', audio_text)
return Response({
"response":audio_text
})
# test api
class TestAPI(APIView):
# retrieve all the details
def get(self, request):
lecturer_videos = LecturerVideo.objects.all()
lecturer_vidoe_serializer = LecturerVideoSerializer(lecturer_videos, many=True)
data = lecturer_vidoe_serializer.data
return Response({
"response": data
})
def post(self, request):
name = request.data['name']
path = request.data['path']
duration = request.data['duration']
hours = request.data['hours']
minutes = request.data['minutes']
seconds = request.data['seconds']
# create the LecturerVideo details
LecturerVideo(
id=2,
name=name,
path=path,
duration=duration,
hours=hours,
minutes=minutes,
seconds=seconds
).save()
return Response({
"response": "Success"
})
# this API will retrieve lecture audio text details
class LectureAudioTextAPI(APIView):
def get(self, request):
lecture_audio_text = LecturerAudioText.objects.all()
lecture_audio_text_serializer = LecturerAudioTextSerializer(lecture_audio_text, many=True)
data = lecture_audio_text_serializer.data
return Response({
"response": data
})
# this API will retrieve lectuer audio summary for given period
class LecturerAudioSummaryPeriodAPI(APIView):
def get(self, request):
print('hello')
option = request.query_params.get('option')
int_option = int(option)
# i cheated here (remove this once you have many recent records) - ok
int_option = 150
isRecordFound = False
lec_audio_text_stats = []
labels = []
current_date = datetime.datetime.now().date()
option_date = datetime.timedelta(days=int_option)
previous_date = current_date - option_date
lec_audio_text = LecturerAudioText.objects.filter(
lecturer_audio_original_text__lecture_audio_id__lecturer_date__gte=previous_date,
lecturer_audio_original_text__lecture_audio_id__lecturer_date__lte=current_date
)
# if there are records
if len(lec_audio_text) > 0:
isRecordFound = True
lec_audio_text_ser = LecturerAudioTextSerializer(lec_audio_text, many=True)
lec_audio_text_data = lec_audio_text_ser.data
lec_audio_text_stats, labels = ta.get_lecturer_audio_summary_for_period(lec_audio_text_data)
return Response({ return Response({
"response":analysis "statistics": lec_audio_text_stats,
"labels": labels,
"isRecordFound": isRecordFound
}) })
...@@ -8,11 +8,18 @@ import os ...@@ -8,11 +8,18 @@ import os
def activity_recognition(video_name): def activity_recognition(video_name):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
CLASSIFIER_DIR = os.path.join(BASE_DIR, "MonitorLecturerApp\\models") CLASSIFIER_DIR = os.path.join(BASE_DIR, "MonitorLecturerApp\\models")
VIDEO_PATH = os.path.join(BASE_DIR, "assets\\FirstApp\\lecturer_videos\\{}".format(video_name)) # VIDEO_PATH = os.path.join(BASE_DIR, "assets\\FirstApp\\lecturer_videos\\{}".format(video_name)) -> Uncomment after integration
VIDEO_PATH = os.path.join(BASE_DIR, "static\\FirstApp\\lecturer_videos\\{}".format(video_name))
print('video name: ', video_name) print('video name: ', video_name)
detector_path = os.path.join(CLASSIFIER_DIR, "keras_model.h5") # detector_path = os.path.join(CLASSIFIER_DIR, "keras_model.h5")
detector_path = os.path.join(CLASSIFIER_DIR, "keras_model_updated.h5")
# Disable scientific notation for clarity # Disable scientific notation for clarity
np.set_printoptions(suppress=True) np.set_printoptions(suppress=True)
...@@ -50,9 +57,9 @@ def activity_recognition(video_name): ...@@ -50,9 +57,9 @@ def activity_recognition(video_name):
# getting the number of frames using CAP_PROP_FRAME_COUNT method # getting the number of frames using CAP_PROP_FRAME_COUNT method
no_of_frames = video.get(cv2.CAP_PROP_FRAME_COUNT) no_of_frames = video.get(cv2.CAP_PROP_FRAME_COUNT)
frame_count = 0 frame_count = 0
seated_count = 0 seated_count = 0.0
standing_count = 0 standing_count = 0.0
walking_count = 0 walking_count = 0.0
# while loop is conditioned like this to avoid the termination of the loop with an exception # while loop is conditioned like this to avoid the termination of the loop with an exception
while (frame_count < no_of_frames): while (frame_count < no_of_frames):
...@@ -88,13 +95,15 @@ def activity_recognition(video_name): ...@@ -88,13 +95,15 @@ def activity_recognition(video_name):
# if cv2.waitKey(1) & 0xFF == ord('q'): # if cv2.waitKey(1) & 0xFF == ord('q'):
# break # break
cv2.destroyAllWindows() cv2.destroyAllWindows()
print("No of frames: ", frame_count) print("No of frames: ", frame_count)
print("No of frames in seated_count: ", seated_count)
print("No of frames in standing_count: ", standing_count)
print("No of frames in walking_count: ", walking_count)
# calculating the percentages # calculating the percentages
sit_perct = (seated_count / no_of_frames) * 100 sit_perct = (seated_count / no_of_frames) * 100
stand_perct = (standing_count / no_of_frames) * 100 stand_perct = (standing_count / no_of_frames) * 100
walk_perct = (walking_count / no_of_frames) * 100 walk_perct = (walking_count / no_of_frames) * 100
......
...@@ -46,7 +46,7 @@ def run(): ...@@ -46,7 +46,7 @@ def run():
else: else:
d[word] = 1 d[word] = 1
# the key words are "extraneous filler words(ok, well, like, Actually, Basically, that, jest, only, really, very, now, simply, maybe, perhaps, somehow, almost, slightly, seemed ....)" # the key words are "extraneous filler words (ok, well, like, Actually, Basically, that, jest, only, really, very, now, simply, maybe, perhaps, somehow, almost, slightly, seemed ....)"
for key in list(d.keys()): for key in list(d.keys()):
if (key == "like"): if (key == "like"):
...@@ -170,3 +170,46 @@ def run(): ...@@ -170,3 +170,46 @@ def run():
analysis['non_lexical_count'] = non_lexical_count analysis['non_lexical_count'] = non_lexical_count
return analysis return analysis
# this method will return the lecturer audio summary for period
def get_lecturer_audio_summary_for_period(lecture_audio_text_data):
# declare variables to add percentage values
word_count = 0
lexical_count_combined = 0
non_lexical_count_combined = 0
# get the number of activties to calculate average
no_of_data = len(lecture_audio_text_data)
individual_lec_data = []
labels = ["lexical_wordcount", "non_lexical_wordcount", "wordcount"]
# iterate through the activities
for audio_data in lecture_audio_text_data:
ind_word_count = int(audio_data["lecturer_audio_text_lexical_wordcount"])
ind_lexical_count = int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
ind_non_lexical_count = int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
individual_lecture = {}
individual_lecture["lexical_wordcount"] = int(audio_data["lecturer_audio_text_lexical_wordcount"])
individual_lecture["non_lexical_wordcount"] = int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
individual_lecture["wordcount"] = int(audio_data["lecturer_audio_text_wordcount"])
lexical_count_combined += int(audio_data["lecturer_audio_text_lexical_wordcount"])
non_lexical_count_combined += int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
word_count += int(audio_data["lecturer_audio_text_wordcount"])
# calculate the percentages
# individual_lecture["lexical_perct"] = round((ind_lexical_count / ind_word_count), 1)
# individual_lecture["non_lexical_perct"] = round((ind_non_lexical_count / ind_word_count), 1)
# append to the list
individual_lec_data.append(individual_lecture)
return individual_lec_data, labels
\ No newline at end of file
# Generated by Django 3.0.4 on 2020-04-01 15:45 # Generated by Django 2.2.11 on 2020-09-15 07:59
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
...@@ -8,22 +9,13 @@ class Migration(migrations.Migration): ...@@ -8,22 +9,13 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('FirstApp', '0001_initial'),
('LectureSummarizingApp', '0001_initial'),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='RegisterTeacher', name='LecturerVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fName', models.CharField(max_length=15)),
('lName', models.CharField(max_length=15)),
('subject', models.CharField(max_length=50)),
('email', models.CharField(max_length=50)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='tVideo',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)), ('name', models.CharField(max_length=100)),
...@@ -35,7 +27,7 @@ class Migration(migrations.Migration): ...@@ -35,7 +27,7 @@ class Migration(migrations.Migration):
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='tVideoMetaData', name='LecturerVideoMetaData',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fps', models.IntegerField()), ('fps', models.IntegerField()),
...@@ -45,4 +37,38 @@ class Migration(migrations.Migration): ...@@ -45,4 +37,38 @@ class Migration(migrations.Migration):
('walking_count', models.IntegerField()), ('walking_count', models.IntegerField()),
], ],
), ),
migrations.CreateModel(
name='RegisterTeacher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fName', models.CharField(max_length=15)),
('lName', models.CharField(max_length=15)),
('subject', models.CharField(max_length=50)),
('email', models.CharField(max_length=50)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='LectureRecordedVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_video_id', models.CharField(max_length=10)),
('lecturer_date', models.DateField()),
('lecture_video_name', models.CharField(max_length=50)),
('lecture_video_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LecturerAudioText',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecturer_audio_text_id', models.CharField(max_length=10)),
('lecturer_audio_text_wordcount', models.IntegerField()),
('lecturer_audio_text_lexical_wordcount', models.IntegerField()),
('lecturer_audio_text_non_lexical_wordcount', models.IntegerField()),
('lecturer_audio_original_text', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='LectureSummarizingApp.LectureAudioSummary')),
],
),
] ]
# Generated by Django 2.2.11 on 2020-09-15 09:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('MonitorLecturerApp', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='lectureraudiotext',
name='lecturer_audio_text_status',
field=models.CharField(choices=[(1, 'Below'), (2, 'Average'), (3, 'Excellent')], default='Average', max_length=15),
),
]
# Generated by Django 2.2.11 on 2020-09-15 09:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('MonitorLecturerApp', '0002_lectureraudiotext_lecturer_audio_text_status'),
]
operations = [
migrations.AlterField(
model_name='lectureraudiotext',
name='lecturer_audio_text_status',
field=models.CharField(choices=[('Below', 'Below'), ('Average', 'Average'), ('Excellent', 'Excellent')], default='Average', max_length=15),
),
]
...@@ -2,6 +2,9 @@ from django.db import models ...@@ -2,6 +2,9 @@ from django.db import models
from djongo import models from djongo import models
# Create your models here. # Create your models here.
from FirstApp.MongoModels import Subject, Lecturer
from LectureSummarizingApp.models import LectureAudioSummary
class RegisterTeacher(models.Model): class RegisterTeacher(models.Model):
fName = models.CharField(max_length = 15) fName = models.CharField(max_length = 15)
...@@ -14,7 +17,7 @@ class RegisterTeacher(models.Model): ...@@ -14,7 +17,7 @@ class RegisterTeacher(models.Model):
return self.fName return self.fName
class tVideo(models.Model): class LecturerVideo(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
path = models.CharField(max_length=100) path = models.CharField(max_length=100)
duration = models.CharField(max_length=100) duration = models.CharField(max_length=100)
...@@ -26,7 +29,7 @@ class tVideo(models.Model): ...@@ -26,7 +29,7 @@ class tVideo(models.Model):
return self.name return self.name
class tVideoMetaData(models.Model): class LecturerVideoMetaData(models.Model):
fps = models.IntegerField() fps = models.IntegerField()
frame_count = models.IntegerField() frame_count = models.IntegerField()
seated_count = models.IntegerField() seated_count = models.IntegerField()
...@@ -51,18 +54,32 @@ class tVideoMetaData(models.Model): ...@@ -51,18 +54,32 @@ class tVideoMetaData(models.Model):
self.calWalkPercent() self.calWalkPercent()
class lectureAudio (models.Model): class LecturerAudioText (models.Model):
lecture_audio_id = models.CharField(max_length=10) lecturer_audio_text_id = models.CharField(max_length=10)
lecturer_date = models.DateField() lecturer_audio_text_wordcount = models.IntegerField()
lecture_audio_name = models.CharField(max_length=50) lecturer_audio_text_lexical_wordcount = models.IntegerField()
lecture_audio_length = models.DurationField() lecturer_audio_text_non_lexical_wordcount = models.IntegerField()
# lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0) lecturer_audio_text_status = models.CharField(
# subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0) max_length=15,
choices=(
("Below", "Below"),
("Average", "Average"),
("Excellent", "Excellent")
),
default="Average"
)
lecturer_audio_original_text = models.ForeignKey(LectureAudioSummary, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.lecturer_audio_text_id
class lectureRecordedVideo (models.Model): class LectureRecordedVideo (models.Model):
lecture_video_id = models.CharField(max_length=10) lecture_video_id = models.CharField(max_length=10)
lecturer_date = models.DateField() lecturer_date = models.DateField()
lecture_video_name = models.CharField(max_length=50) lecture_video_name = models.CharField(max_length=50)
lecture_video_length = models.DurationField() lecture_video_length = models.DurationField()
# lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0) lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0)
# subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0) subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0)
\ No newline at end of file
def __str__(self):
return self.lecture_video_id
\ No newline at end of file
from rest_framework import serializers from rest_framework import serializers
from .models import RegisterTeacher, tVideoMetaData
class RegisterTeacherSerializer(serializers.ModelSerializer): from FirstApp.serializers import LecturerSerializer, SubjectSerializer
from LectureSummarizingApp.models import LectureAudioSummary
from .models import RegisterTeacher
from .models import LecturerAudioText, LecturerVideoMetaData, LecturerVideo, LectureRecordedVideo
class RegisterTeacherSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = RegisterTeacher model = RegisterTeacher
fields = {'fName', 'lName', 'subject', 'email', 'password'} fields = {'fName', 'lName', 'subject', 'email', 'password'}
class LecturerVideoSerializer(serializers.ModelSerializer):
class Meta:
model = LecturerVideo
fields = '__all__'
class LecturerVideoMetaDataSerializer(serializers.ModelSerializer):
class Meta:
model = LecturerVideoMetaData
fields = '__all__'
class LecturerAudioTextSerializer(serializers.ModelSerializer):
lecturer_audio_original_text = LectureAudioSummary()
class Meta:
model = LecturerAudioText
fields = '__all__'
class LectureRecordedVideoSerializer(serializers.ModelSerializer):
lecturer = LecturerSerializer()
subject = SubjectSerializer()
class Meta:
model = LectureRecordedVideo
fields = '__all__'
<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title:{
text: "Daily High Temperature at Different Beaches"
},
axisX: {
valueFormatString: "DD MMM,YY"
},
axisY: {
title: "Temperature (in °C)",
suffix: " °C"
},
legend:{
cursor: "pointer",
fontSize: 16,
itemclick: toggleDataSeries
},
toolTip:{
shared: true
},
data: [{
name: "Myrtle Beach",
type: "spline",
yValueFormatString: "#0.## °C",
showInLegend: true,
dataPoints: [
{ x: new Date(2017,6,24), y: 31 },
{ x: new Date(2017,6,25), y: 31 },
{ x: new Date(2017,6,26), y: 29 },
{ x: new Date(2017,6,27), y: 29 },
{ x: new Date(2017,6,28), y: 31 },
{ x: new Date(2017,6,29), y: 30 },
{ x: new Date(2017,6,30), y: 29 }
]
},
{
name: "Martha Vineyard",
type: "spline",
yValueFormatString: "#0.## °C",
showInLegend: true,
dataPoints: [
{ x: new Date(2017,6,24), y: 20 },
{ x: new Date(2017,6,25), y: 20 },
{ x: new Date(2017,6,26), y: 25 },
{ x: new Date(2017,6,27), y: 25 },
{ x: new Date(2017,6,28), y: 25 },
{ x: new Date(2017,6,29), y: 25 },
{ x: new Date(2017,6,30), y: 25 }
]
},
{
name: "Nantucket",
type: "spline",
yValueFormatString: "#0.## °C",
showInLegend: true,
dataPoints: [
{ x: new Date(2017,6,24), y: 22 },
{ x: new Date(2017,6,25), y: 19 },
{ x: new Date(2017,6,26), y: 23 },
{ x: new Date(2017,6,27), y: 24 },
{ x: new Date(2017,6,28), y: 24 },
{ x: new Date(2017,6,29), y: 23 },
{ x: new Date(2017,6,30), y: 23 }
]
}]
});
chart.render();
function toggleDataSeries(e){
if (typeof(e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
}
else{
e.dataSeries.visible = true;
}
chart.render();
}
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 300px; max-width: 1400px; margin: 0px auto;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
...@@ -15,24 +13,31 @@ ...@@ -15,24 +13,31 @@
{% load static %} {% load static %}
<!-- Custom fonts for this template--> <!-- Custom fonts for this template-->
<link rel="shortcut icon" href="{% static 'FirstApp/images/favicon.ico' %}" type="image/x-icon" /> <link rel="shortcut icon" href="{% static 'FirstApp/images/favicon.ico' %}" type="image/x-icon"/>
<link href="{% static 'FirstApp/css/all.min.css' %}" rel="stylesheet" type="text/css"> <link href="{% static 'FirstApp/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template--> <!-- Custom styles for this template-->
<link href="{% static 'FirstApp/css/sb-admin-2.min.css' %}" rel="stylesheet"> <link href="{% static 'FirstApp/css/sb-admin-2.min.css' %}" rel="stylesheet">
</head> </head>
<body id="page-top"> <body id="page-top">
<!-- Bootstrap core JavaScript--> <!-- Bootstrap core JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery/jquery.min.js' %}"></script> <script src="{% static 'FirstApp/vendor/jquery/jquery.min.js' %}"></script>
<script src="{% static 'FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script> <script src="{% static 'FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<script type="text/javascript"> <!-- canvasJS implementation -->
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript">
var global_lecturer_id = 0;
var lecture_audio_text_summary = {};
$(document).ready(function () { $(document).ready(function () {
$('.calc').click(function () { $('.calc').click(function () {
let video_name = $(this).attr('id'); let video_name = $(this).attr('id');
...@@ -57,13 +62,14 @@ ...@@ -57,13 +62,14 @@
$('#progress_bars').attr('hidden', false); $('#progress_bars').attr('hidden', false);
$('#loader').attr('hidden', true); $('#loader').attr('hidden', true);
{#let sitting = Math.round(percentages.sitting_perct);#}
let sitting = Math.round(percentages.sitting_perct); let sitting = Math.round(percentages.sitting_perct);
let standing = Math.round(percentages.standing_perct); let standing = Math.round(percentages.standing_perct);
let walking = Math.round(percentages.walking_perct); let walking = Math.round(percentages.walking_perct);
$('#sitting_val').width(sitting+'%'); $('#sitting_val').width(sitting + '%');
$('#standing_val').width(standing+'%'); $('#standing_val').width(standing + '%');
$('#walking_val').width(walking+'%'); $('#walking_val').width(walking + '%');
$('#sitting_span').text(sitting + '%'); $('#sitting_span').text(sitting + '%');
$('#standing_span').text(standing + '%'); $('#standing_span').text(standing + '%');
...@@ -72,7 +78,7 @@ ...@@ -72,7 +78,7 @@
} }
/*
//this is for the temporay button (delete later) //this is for the temporay button (delete later)
$('#temp_btn').click(function () { $('#temp_btn').click(function () {
//using the fecth API //using the fecth API
...@@ -89,23 +95,201 @@ ...@@ -89,23 +95,201 @@
.catch((err) => alert('this is a error: ' + err)) .catch((err) => alert('this is a error: ' + err))
}); });
*/
//this function will display the retrieved audio analysis values //this function will display the retrieved audio analysis values
function displayAudioAnalysis(response) { function displayAudioAnalysis(response) {
$('#num_of_words').text(response.num_of_words);
$('#lexical_count').text(response.lexical_count); if (response) {
$('#non_lexical_count').text(response.non_lexical_count);
$('#num_of_words').text(response.lecturer_audio_text_wordcount);
$('#lexical_count').text(response.lecturer_audio_text_lexical_wordcount);
$('#non_lexical_count').text(response.lecturer_audio_text_non_lexical_wordcount);
//hide the loader //hide the loader
$('#audio_loader').attr('hidden', true); $('#audio_loader').attr('hidden', true);
//show the content //show the content
$('#audio_summary_details').attr('hidden', false); $('#audio_summary_details').attr('hidden', false);
} else {
alert("No audio summary details... Try again!");
}
} }
$('#summary_btn').click(function () {
//open the modal
$('#audio_summary_modal').modal();
}); });
</script>
//this function will handle the audio list radio buttons
$('.audio_radio').click(function () {
lec_audio_id = $(this).attr('data-id');
global_lecturer_id = Number($(this).attr('data-lecturer'));
//hide the message
$('#no_content_audio_message').attr('hidden', true);
//show the loader
$('#audio_loader').attr('hidden', false);
//display the modal
{#$('#lecturer_behavior_view_summary_modal').modal();#}
fetch('http://127.0.0.1:8000/lecturer/get-audio-analysis/?audio_id=' + lec_audio_id)
.then((res) => res.json())
.then((out) => displayAudioAnalysis(out.response))
.catch((err) => alert('this is a error: ' + err))
});
$('#audio_graph').click(function () {
//display the option modal
$('#lecturer_behavior_view_summary_modal').modal();
});
//this function will handle the view summary option form
$('#view_summary_option_form').submit(function (e) {
let option = $("input[name='option']:checked").val();
e.preventDefault();
//send the data using fetch API
fetch('http://127.0.0.1:8000/lecturer/get-lecturer-audio-summary-for-period/?option=' + option)
.then((res) => res.json())
.then((out) => displayPeriodStudentActivitySummary(out))
.catch((err) => alert('error: ' + err))
});
//this function will display the summary graph
function displayPeriodStudentActivitySummary(res) {
if (res.isRecordFound) {
lecture_audio_text_summary = res;
renderLectureAudioTextStatistics();
//hide the previous modal
$('#lecturer_behavior_view_summary_modal').modal("hide");
//display the modal
$('#audio_text_stats_modal').modal();
} else {
alert('nothing found');
}
}
//this function will render the chart for Activity statistics
function renderLectureAudioTextStatistics() {
let individual_activities = lecture_audio_text_summary.statistics;
let activity_labels = lecture_audio_text_summary.labels;
let activity_length = lecture_audio_text_summary.statistics.length;
let label_length = activity_labels.length;
let data = [];
for (let i = 0; i < label_length; i++) {
let label = activity_labels[i];
let datapoints = [];
for (let j = 0; j < activity_length; j++) {
let activity = individual_activities[j];
datapoints.push({label: "lecture " + (j + 1), y: activity[label]});
}
let obj = {
type: "line",
showInLegend: true,
name: label,
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "Lec " + (i + 1),
color: getRandomColor(),
dataPoints: datapoints
};
data.push(obj);
}
var chart = new CanvasJS.Chart("audio_text_stats_chart", {
animationEnabled: true,
theme: "light2",
title: {
text: "Audio Statistics"
},
axisX: {
title: "Lecture",
{#valueFormatString: "DD MMM",#}
valueFormatString: "lec",
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Count",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "bottom",
horizontalAlign: "center",
{#dockInsidePlotArea: true,#}
itemclick: toogleDataSeries
},
data: data
});
chart.render();
}
//this function will generate random colors
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
//this function will toggle the content
function toogleDataSeries(e) {
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
chart.render();
}
});
</script>
<!-- Page Wrapper --> <!-- Page Wrapper -->
<div id="wrapper"> <div id="wrapper">
...@@ -142,13 +326,14 @@ ...@@ -142,13 +326,14 @@
<!-- Nav Item - Pages Collapse Menu --> <!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item"> <li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true" aria-controls="collapsePages"> <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i> <i class="fas fa-fw fa-folder"></i>
<span>Pages</span> <span>Pages</span>
</a> </a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar"> <div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded"> <div class="bg-white py-2 collapse-inner rounded">
<!-- <h6 class="collapse-header">Login Screens:</h6>--> <!-- <h6 class="collapse-header">Login Screens:</h6>-->
<a class="collapse-item" href="index.html">Dashboard</a> <a class="collapse-item" href="index.html">Dashboard</a>
<a class="collapse-item" href="/lecturer/lecture-video">Video Page</a> <a class="collapse-item" href="/lecturer/lecture-video">Video Page</a>
...@@ -183,8 +368,9 @@ ...@@ -183,8 +368,9 @@
<!-- Page Heading --> <!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4"> <div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Dashboard</h1> <h1 class="h3 mb-0 text-gray-800">Lecturer Performance Evaluation System</h1>
<a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-download fa-sm text-white-50"></i> Generate Report</a> {# <a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i#}
{# class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>#}
</div> </div>
...@@ -193,38 +379,56 @@ ...@@ -193,38 +379,56 @@
<div class="row"> <div class="row">
<!-- Area Chart --> <!-- Area Chart -->
<div class="col-xl-5 col-lg-7"> <div class="col-lg-6 mb-4">
<div class="card shadow mb-4"> <div class="card shadow mb-4">
<!-- Card Header - Dropdown --> <!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between"> <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Audio List</h6> <h6 class="m-0 font-weight-bold text-primary">Audio List</h6>
<button type="button" class="btn btn-outline-primary" id="audio_graph">Statistics
</button>
</div> </div>
<!-- Card Body --> <!-- Card Body -->
<div class="card-body"> <div class="card-body">
<div class="card-body"> <div class="card-body" style="overflow-y: scroll">
<!-- <div class="chart-pie pt-4 pb-2">--> <div class="chart-pie pt-4 pb-2">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>Audio Name</th> <th></th>
<th>Duration</th> <th>Date</th>
<th>Subject</th>
<th>Lecturer</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<!-- {% for video in Videos %}--> <!-- {% for audio in lec_list %}-->
<tr> <tr>
<!-- <td>{{video.name}}</td>--> <td>
<!-- <td>{{video.duration}}</td>--> <div class="radio">
<label>
<input type="radio" class="audio_radio"
name="audio_radio" id="{{ audio.date }}"
data-id="{{ audio.id }}"
data-lecturer="{{ audio.lecturer_id }}">
</label>
</div>
</td>
<td>{{ audio.date }}</td>
<td>{{ audio.subject }}</td>
<td>{{ audio.lecturer }}</td>
</tr> </tr>
<!-- {% endfor %}-->
<!-- {% endfor %}-->
</tbody> </tbody>
</table> </table>
<!-- </div>--> </div>
<!--this is a temporary button --> <!--this is a temporary button -->
<div class="float-right m-3"> <div class="float-right m-3">
<button type="button" class="btn btn-danger" id="temp_btn">Temp</button>
{# <button type="button" class="btn btn-danger" id="temp_btn">Temp</button>#}
</div> </div>
</div> </div>
...@@ -234,15 +438,17 @@ ...@@ -234,15 +438,17 @@
</div> </div>
<!-- Video List --> <!-- Video List -->
<div class="col-xl-6 col-lg-5"> <div class="col-lg-6 mb-4">
<div class="card shadow mb-4"> <div class="card shadow mb-4">
<!-- Card Header - Dropdown --> <!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between"> <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Video List</h6> <h6 class="m-0 font-weight-bold text-primary">Video List</h6>
{# <button type="button" class="btn btn-outline-primary" id="video_graph">Statistics#}
{# </button>#}
</div> </div>
<!-- Card Body --> <!-- Card Body -->
<div class="card-body"> <div class="card-body" style="overflow-y: scroll">
<div class="chart-pie pt-4 pb-2"> <div class="chart-pie pt-4 pb-2">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
...@@ -255,10 +461,12 @@ ...@@ -255,10 +461,12 @@
<tbody> <tbody>
{% for video in Videos %} {% for video in Videos %}
<tr> <tr>
<td>{{video.name}}</td> <td>{{ video.name }}</td>
<td>{{video.duration}}</td> <td>{{ video.duration }}</td>
<td class="btn_class"> <td class="btn_class">
<button type="button" class="btn btn-success calc" id='{{video.name}}'>Calculate</button> <button type="button" class="btn btn-success calc"
id='{{ video.name }}'>Calculate
</button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
...@@ -290,6 +498,8 @@ ...@@ -290,6 +498,8 @@
<!--loader --> <!--loader -->
<div class="text-center" id="audio_loader" hidden> <div class="text-center" id="audio_loader" hidden>
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="">#}
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt=""> <img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="">
</div> </div>
...@@ -309,18 +519,29 @@ ...@@ -309,18 +519,29 @@
<td id="num_of_words"></td> <td id="num_of_words"></td>
</tr> </tr>
<tr> <tr>
<td>No of extraneous words</td> <td>No fo word to be expected</td>
<td id="lexical_count"></td> <td> 3600 - 4800</td>
</tr>
<tr>
<td>No of Non-lexical words</td>
<td id="non_lexical_count"></td>
</tr> </tr>
{# <tr>#}
{# <td>No of extraneous words</td>#}
{# <td id="lexical_count"></td>#}
{# </tr>#}
{# <tr>#}
{# <td>No of Non-lexical words</td>#}
{# <td id="non_lexical_count"></td>#}
{# </tr>#}
</tbody> </tbody>
</table> </table>
<!--button --> <!--button -->
{# <div class="float-right">#}
{# <button type="button" class="btn btn-outline-primary m-3" id="summary_btn">View More</button>#}
{# </div>#}
<div class="float-right"> <div class="float-right">
<button type="button" class="btn btn-outline-primary m-3" id="summary_btn">View More</button> <button type="button" class="btn btn-outline-primary m-3" id="summary_btn">View More
Test
</button>
</div> </div>
</div> </div>
...@@ -338,13 +559,13 @@ ...@@ -338,13 +559,13 @@
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="text-center" id="no_content_message"> <div class="text-center" id="no_content_message">
<span class="font-italic">No content to be displayed</span> <span class="font-italic">No video content to be displayed</span>
</div> </div>
<!--loader --> <!--loader -->
<div class="text-center" id="loader" hidden> <div class="text-center" id="video_loader" hidden>
<!-- <img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="">-->
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt=""> <img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader">
</div> </div>
...@@ -379,15 +600,15 @@ ...@@ -379,15 +600,15 @@
</div> </div>
<!-- Approach --> <!-- Approach -->
<!-- <div class="card shadow mb-4">--> <!-- <div class="card shadow mb-4">-->
<!-- <div class="card-header py-3">--> <!-- <div class="card-header py-3">-->
<!-- <h6 class="m-0 font-weight-bold text-primary">Development Approach</h6>--> <!-- <h6 class="m-0 font-weight-bold text-primary">Development Approach</h6>-->
<!-- </div>--> <!-- </div>-->
<!-- <div class="card-body">--> <!-- <div class="card-body">-->
<!--&lt;!&ndash; <p>SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce CSS bloat and poor page performance. Custom CSS classes are used to create custom components and custom utility classes.</p>&ndash;&gt;--> <!--&lt;!&ndash; <p>SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce CSS bloat and poor page performance. Custom CSS classes are used to create custom components and custom utility classes.</p>&ndash;&gt;-->
<!--&lt;!&ndash; <p class="mb-0">Before working with this theme, you should become familiar with the Bootstrap framework, especially the utility classes.</p>&ndash;&gt;--> <!--&lt;!&ndash; <p class="mb-0">Before working with this theme, you should become familiar with the Bootstrap framework, especially the utility classes.</p>&ndash;&gt;-->
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
</div> </div>
</div> </div>
...@@ -420,7 +641,8 @@ ...@@ -420,7 +641,8 @@
</a> </a>
<!-- Logout Modal--> <!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -438,6 +660,168 @@ ...@@ -438,6 +660,168 @@
</div> </div>
</div> </div>
<!-- audio summary Modal qualitative analysis -->
<div class="modal fade" id="audio_summary_modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Audio summary</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<table class="table table-borderless">
<tbody>
<tr>
<td>No. of extraneous words</td>
<td id="lexical_count"></td>
</tr>
<tr>
<td>No. of non-lexical words</td>
<td id="non_lexical_count"></td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-danger" type="button" data-dismiss="modal">Done</button>
<!-- <a class="btn btn-primary" href="login.html">Logout</a>-->
</div>
</div>
</div>
</div>
<!-- Graph audio summary -->
{#<div class="modal fade" id="audio_summary_graph" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"#}
{# aria-hidden="true">#}
{# <div class="modal-dialog" role="document" style="max-width: 900px; max-height: 750px">#}
{# <div class="modal-content">#}
{# <div class="modal-header">#}
{# <h5 class="modal-title">Audio Summary Graph</h5>#}
{# <button class="close" type="button" data-dismiss="modal" aria-label="Close">#}
{# <span aria-hidden="true">×</span>#}
{# </button>#}
{# </div>#}
{# <div class="modal-body">#}
{##}
{# <div id="chartContainer" style="height: 400px; max-width: 8000px; margin: 0px auto;"></div>#}
{##}
{# </div>#}
{# <div class="modal-footer">#}
{# <button class="btn btn-danger" type="button" data-dismiss="modal">Done</button>#}
{# </div>#}
{# </div>#}
{# </div>#}
{#</div>#}
<!-- Graph Video Summary -->
<div class="modal fade" id="video_summary_graph" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 900px; max-height: 750px">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Video Summary Graph</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="chartContainerVideo" style="height: 400px; max-width: 8000px; margin: 0px auto;"></div>
</div>
<div class="modal-footer">
<button class="btn btn-danger" type="button" data-dismiss="modal">Done</button>
</div>
</div>
</div>
</div>
<!-- lecture behavior view summary modal -->
<div class="modal fade" id="lecturer_behavior_view_summary_modal" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 500px">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="exampleModalLabel">View Summary Options</h3>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<h5>View Summary for...</h5>
</div>
<!-- list of options -->
<form action="#" method="get" id="view_summary_option_form">
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio" name="option" value="7">
<label class="custom-control-label" for="customRadio">one week</label>
</div>
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio1" name="option" value="14">
<label class="custom-control-label" for="customRadio1">2 weeks</label>
</div>
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio2" name="option" value="30">
<label class="custom-control-label" for="customRadio2">one month</label>
</div>
<div class="form-group mt-4">
<button type="submit" class="btn btn-outline-success" id="submit_view_summary_option">
Submit
</button>
</div>
</form>
<!-- end of list of options -->
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
<!-- end of lecturer behavior view summary modal -->
<!-- Audio Data statistics Modal-->
<div class="modal fade" id="audio_text_stats_modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 1400px">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Audio Data Statistics</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body text-center">
<div id="audio_text_stats_chart" style="height: 370px; width: 100%"></div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
<!-- end of activity statistics modal -->
{% load static %} {% load static %}
......
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
</div> </div>
<!-- Card Body --> <!-- Card Body -->
<div class="card-body"> <div class="card-body" style="overflow-y: scroll">
<div class="chart-pie pt-4 pb-2"> <div class="chart-pie pt-4 pb-2">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
......
...@@ -28,7 +28,16 @@ urlpatterns = [ ...@@ -28,7 +28,16 @@ urlpatterns = [
url(r'^activities/$', api.ActivityRecognitionAPI.as_view()), url(r'^activities/$', api.ActivityRecognitionAPI.as_view()),
# API to retrieve audio analysis # API to retrieve audio analysis
url(r'^get-audio-analysis', api.GetLectureAudioAnalysis.as_view()), url(r'^get-audio-analysis/$', api.GetLectureAudioAnalysis.as_view()),
# API to retrieve lecture audio text
url(r'^get-lecture-audio-text', api.LectureAudioTextAPI.as_view()),
# API to retrieve lecture audio text
url(r'^get-lecturer-audio-summary-for-period', api.LecturerAudioSummaryPeriodAPI.as_view()),
# test API
url(r'^test-api', api.TestAPI.as_view()),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
......
...@@ -4,13 +4,17 @@ from django.conf.urls import url ...@@ -4,13 +4,17 @@ from django.conf.urls import url
from rest_framework import routers from rest_framework import routers
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from LectureSummarizingApp.models import LectureAudio
from LectureSummarizingApp.serializer import LectureAudioSerializer
from . import views from . import views
from . models import RegisterTeacher, tVideo from .models import RegisterTeacher, LecturerVideo
from . serializers import RegisterTeacherSerializer from . serializers import RegisterTeacherSerializer
import cv2 import cv2
import os import os
import datetime import datetime
from datetime import datetime as dt
...@@ -45,8 +49,29 @@ def hello(request): ...@@ -45,8 +49,29 @@ def hello(request):
videos = [] videos = []
durations = [] durations = []
# retrieve audio details from db
lecture_audio = LectureAudio.objects.all()
lec_audio_serializer = LectureAudioSerializer(lecture_audio, many=True)
lec_audio_data = lec_audio_serializer.data
lec_list = []
for audio in lec_audio_data:
lec_audio_object = {}
lec_audio_object["id"] = audio["id"]
lec_audio_object["date"] = audio["lecturer_date"]
lec_audio_object["subject"] = audio["subject"]["name"]
lec_audio_object["lecturer"] = audio["lecturer"]["fname"] + " " + audio["lecturer"]["lname"]
lec_audio_object["lecturer_id"] = audio["lecturer"]["id"]
# append to the list
lec_list.append(lec_audio_object)
# the list needs to be sorted by the date
lec_list.sort(key=lambda date: dt.strptime(str(date['date']), "%Y-%m-%d"), reverse=True)
for videoPath in videoPaths: for videoPath in videoPaths:
video = tVideo() video = LecturerVideo()
cap = cv2.VideoCapture(videoPath) cap = cv2.VideoCapture(videoPath)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS" fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
...@@ -60,7 +85,7 @@ def hello(request): ...@@ -60,7 +85,7 @@ def hello(request):
video.duration = str(durationObj) video.duration = str(durationObj)
videos.append(video) videos.append(video)
print('Video Name: ', video.name) print('Video Name: ', video.name)
context = {'object': obj, 'Videos': videos, 'durations': durations, 'template_name': 'MonitorLecturerApp/template.html'} context = {'object': obj, 'Videos': videos, 'durations': durations, 'template_name': 'MonitorLecturerApp/template.html', 'lec_list': lec_list}
return render(request, 'MonitorLecturerApp/index.html', context) return render(request, 'MonitorLecturerApp/index.html', context)
...@@ -108,7 +133,7 @@ def lecVideo(request): ...@@ -108,7 +133,7 @@ def lecVideo(request):
durations = [] durations = []
for videoPath in videoPaths: for videoPath in videoPaths:
video = tVideo() video = LecturerVideo()
cap = cv2.VideoCapture(videoPath) cap = cv2.VideoCapture(videoPath)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS" fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
......
...@@ -35,6 +35,7 @@ INSTALLED_APPS = [ ...@@ -35,6 +35,7 @@ INSTALLED_APPS = [
'FirstApp.apps.FirstappConfig', 'FirstApp.apps.FirstappConfig',
'AttendanceApp.apps.AttendanceappConfig', 'AttendanceApp.apps.AttendanceappConfig',
'MonitorLecturerApp.apps.MonitorlecturerappConfig', 'MonitorLecturerApp.apps.MonitorlecturerappConfig',
'LectureSummarizingApp.apps.LectureSummarizingAppConfig',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
......
...@@ -22,5 +22,6 @@ urlpatterns = [ ...@@ -22,5 +22,6 @@ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('', include('FirstApp.urls')), path('', include('FirstApp.urls')),
path('attendance/', include('AttendanceApp.urls')), path('attendance/', include('AttendanceApp.urls')),
path('lecturer/', include('MonitorLecturerApp.urls')) path('lecturer/', include('MonitorLecturerApp.urls')),
path('summary/', include('LectureSummarizingApp.urls'))
] ]
absl-py==0.9.0
alabaster==0.7.12
anaconda-client==1.7.2
anaconda-navigator==1.9.7
anaconda-project==0.8.3
asgiref==3.2.3
asn1crypto==1.0.1
astor==0.8.1
astroid==2.3.1
astropy==3.2.1
atomicwrites==1.3.0
attrs==19.2.0
Babel==2.7.0
backcall==0.1.0
backports.functools-lru-cache==1.5
backports.os==0.1.1
backports.shutil-get-terminal-size==1.0.0
backports.tempfile==1.0
backports.weakref==1.0.post1
beautifulsoup4==4.8.0
bitarray==1.0.1
bkcharts==0.2
bleach==3.1.0
bokeh==1.3.4
bootstrap4==0.1.0
boto==2.49.0
Bottleneck==1.2.1
bson==0.5.8
cachetools==4.0.0
certifi==2019.9.11
cffi==1.12.3
chardet==3.0.4
Click==7.0
cloudpickle==1.2.2
clyent==1.2.2
colorama==0.4.1
comtypes==1.1.7
conda==4.7.12
conda-build==3.18.9
conda-package-handling==1.6.0
conda-verify==3.4.2
contextlib2==0.6.0
cryptography==2.7
cycler==0.10.0
Cython==0.29.13
cytoolz==0.10.0
dask==2.5.2
dataclasses==0.6
decorator==4.4.0
deepspeech==0.7.1
defusedxml==0.6.0
distributed==2.5.2
Django==2.2.12
djangorestframework==3.11.0
djongo==1.3.1
dnspython==1.16.0
docopt==0.6.2
docutils==0.15.2
entrypoints==0.3
et-xmlfile==1.0.1
fastcache==1.1.0
filelock==3.0.12
Flask==1.1.1
fsspec==0.5.2
future==0.17.1
gast==0.2.2
gevent==1.4.0
glob2==0.7
google-auth==1.11.3
google-auth-oauthlib==0.4.1
google-pasta==0.2.0
greenlet==0.4.15
grpcio==1.27.2
h5py==2.9.0
HeapDict==1.0.1
html5lib==1.0.1
idna==2.8
imageio==2.6.0
imagesize==1.1.0
importlib-metadata==0.23
imutils==0.5.3
ipykernel==5.1.2
ipython==7.8.0
ipython-genutils==0.2.0
ipywidgets==7.5.1
isort==4.3.21
itsdangerous==1.1.0
jdcal==1.4.1
jedi==0.15.1
Jinja2==2.10.3
joblib==0.13.2
Js2Py==0.67
json5==0.8.5
jsonschema==3.0.2
jupyter==1.0.0
jupyter-client==5.3.3
jupyter-console==6.0.0
jupyter-core==4.5.0
jupyterlab==1.1.4
jupyterlab-server==1.0.6
Keras==2.3.1
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.0
keyring==18.0.0
kiwisolver==1.1.0
lazy-object-proxy==1.4.2
libarchive-c==2.8
llvmlite==0.29.0
locket==0.2.0
lxml==4.4.1
Markdown==3.2.1
MarkupSafe==1.1.1
matplotlib==3.1.1
mccabe==0.6.1
menuinst==1.4.16
mistune==0.8.4
mkl-fft==1.0.14
mkl-random==1.1.0
mkl-service==2.3.0
mock==3.0.5
more-itertools==7.2.0
mpmath==1.1.0
msgpack==0.6.1
multipledispatch==0.6.0
navigator-updater==0.2.1
nbconvert==5.6.0
nbformat==4.4.0
networkx==2.3
nltk==3.4.5
nose==1.3.7
notebook==6.0.1
numba==0.45.1
numexpr==2.7.0
numpy==1.16.5
numpydoc==0.9.1
oauthlib==3.1.0
olefile==0.46
opencv-python==4.2.0.32
openpyxl==3.0.0
opt-einsum==3.2.0
packaging==19.2
pandas==0.25.1
pandocfilters==1.4.2
parso==0.5.1
partd==1.0.0
path.py==12.0.1
pathlib2==2.3.5
patsy==0.5.1
pep8==1.7.1
pickleshare==0.7.5
Pillow==6.2.0
pipwin==0.4.6
pkginfo==1.5.0.1
pluggy==0.13.0
ply==3.11
prometheus-client==0.7.1
prompt-toolkit==2.0.10
protobuf==3.11.3
psutil==5.6.3
py==1.8.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
PyAudio==0.2.11
pycodestyle==2.5.0
pycosat==0.6.3
pycparser==2.19
pycrypto==2.6.1
pycurl==7.43.0.3
pyflakes==2.1.1
Pygments==2.4.2
pyjsparser==2.7.1
pylint==2.4.2
pymongo==3.10.1
pyodbc==4.0.27
pyOpenSSL==19.0.0
pyparsing==2.4.2
PyPrind==2.11.2
pyreadline==2.1
pyrsistent==0.15.4
PySocks==1.7.1
pytest==5.2.1
pytest-arraydiff==0.3
pytest-astropy==0.5.0
pytest-doctestplus==0.4.0
pytest-openfiles==0.4.0
pytest-remotedata==0.3.2
python-dateutil==2.8.0
pytz==2019.3
PyWavelets==1.0.3
pywin32==223
pywinpty==0.5.5
PyYAML==5.1.2
pyzmq==18.1.0
QtAwesome==0.6.0
qtconsole==4.5.5
QtPy==1.9.0
requests==2.22.0
requests-oauthlib==1.3.0
robobrowser==0.5.3
rope==0.14.0
rsa==4.0
ruamel-yaml==0.15.46
scikit-image==0.15.0
scikit-learn==0.21.3
scipy==1.4.1
seaborn==0.9.0
Send2Trash==1.5.0
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.14.0
snowballstemmer==2.0.0
sortedcollections==1.1.2
sortedcontainers==2.1.0
soupsieve==1.9.3
Sphinx==2.2.0
sphinxcontrib-applehelp==1.0.1
sphinxcontrib-devhelp==1.0.1
sphinxcontrib-htmlhelp==1.0.2
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.2
sphinxcontrib-serializinghtml==1.1.3
sphinxcontrib-websupport==1.1.2
spyder==3.3.6
spyder-kernels==0.5.2
SQLAlchemy==1.3.9
sqlparse==0.2.4
statsmodels==0.10.1
sympy==1.4
tables==3.5.2
tblib==1.4.0
tensorboard==2.1.1
tensorflow==2.1.0
tensorflow-estimator==2.1.0
termcolor==1.1.0
terminado==0.8.2
testpath==0.4.2
toolz==0.10.0
tornado==6.0.3
tqdm==4.36.1
traitlets==4.3.3
tzlocal==2.0.0
unicodecsv==0.14.1
urllib3==1.24.2
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.16.0
widgetsnbextension==3.5.1
win-inet-pton==1.1.0
win-unicode-console==0.5
wincertstore==0.2
wrapt==1.11.2
xlrd==1.2.0
XlsxWriter==1.2.1
xlwings==0.15.10
xlwt==1.3.0
zict==1.0.0
zipp==0.6.0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment