Skip to content

Commit

Permalink
Closed #902 - Fixed bug when maps is not consecutive. Separated endpo…
Browse files Browse the repository at this point in the history
…ints for stats (#904)
  • Loading branch information
glaubervila authored Mar 6, 2024
1 parent 9e0808c commit 8031697
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 119 deletions.
28 changes: 17 additions & 11 deletions backend/tno/prediction_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,20 @@ def sora_occultation_map(


def get_longest_consecutive_numbers(numbers):
# https://stackoverflow.com/questions/55616217/find-longest-consecutive-range-of-numbers-in-list
idx = max(
(
list(map(itemgetter(0), g))
for i, g in groupby(enumerate(np.diff(numbers) == 1), itemgetter(1))
if i
),
key=len,
)
return (idx[0], idx[-1] + 1)
numbers = sorted(numbers)
try:
# https://stackoverflow.com/questions/55616217/find-longest-consecutive-range-of-numbers-in-list
idx = max(
(
list(map(itemgetter(0), g))
for i, g in groupby(enumerate(np.diff(numbers) == 1), itemgetter(1))
if i
),
key=len,
)
return (idx[0], idx[-1] + 1, True)
except:
return (0, -1, False)


def maps_folder_stats():
Expand Down Expand Up @@ -291,13 +295,15 @@ def maps_folder_stats():
if len(maps_dates) > 1:
# Convert dates to integer
date_ints = [d.toordinal() for d in maps_dates]
start, end = get_longest_consecutive_numbers(list(date_ints))
print(date_ints)
start, end, consecutive = get_longest_consecutive_numbers(list(date_ints))
first_map = maps_dates[start]
last_map = maps_dates[end]

result.update(
{
"period": [first_map.isoformat(), last_map.isoformat()],
"period_is_consecutive": consecutive,
"oldest_file": oldest,
"newest_file": newest,
}
Expand Down
54 changes: 30 additions & 24 deletions backend/tno/views/occultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,26 +304,27 @@ def get_queryset(self):
return queryset

@action(detail=False, methods=["get"], permission_classes=(AllowAny,))
def highlights(self, request):
def highlights_unique_asteroids(self, request):

count = Occultation.objects.count()
unique_asteroids = Occultation.objects.values("name").distinct().count()
first_datetime = Occultation.objects.earliest("date_time")
last_datetime = Occultation.objects.latest("date_time")
unique_asteroids = Occultation.objects.values("name").distinct().count()
return Response(
{
"count": count,
"unique_asteroids": unique_asteroids,
"earliest": first_datetime.date_time.isoformat(),
"latest": last_datetime.date_time.isoformat(),
}
)

@action(detail=False, methods=["get"], permission_classes=(AllowAny,))
def highlights_weekly_forecast(self, request):

today_utc = datetime.utcnow().date()
today_events = Occultation.objects.filter(date_time__date=today_utc)

# Total de eventos para hoje que já possuem mapas.
maps_size = []
for event in today_events:
map_filepath = event.get_map_filepath()
if map_filepath.exists():
maps_size.append(map_filepath.stat().st_size)

today_already_have_map = len(maps_size)
total_maps_size = sum(maps_size)

week_number = today_utc.isocalendar().week
next_week_number = week_number + 1

Expand All @@ -333,6 +334,18 @@ def highlights(self, request):
next_week_count = Occultation.objects.filter(
date_time__date__week=next_week_number
).count()
return Response(
{
"today_count": today_events.count(),
"week_count": this_week_count,
"next_week_count": next_week_count,
}
)

@action(detail=False, methods=["get"], permission_classes=(AllowAny,))
def highlights_monthly_forecast(self, request):

today_utc = datetime.utcnow().date()

next_month = today_utc + relativedelta(months=1)
this_month_count = Occultation.objects.filter(
Expand All @@ -342,25 +355,18 @@ def highlights(self, request):
date_time__date__month=next_month.month
).count()

maps_stats = maps_folder_stats()

return Response(
{
"count": count,
"earliest": first_datetime.date_time.isoformat(),
"latest": last_datetime.date_time.isoformat(),
"unique_asteroids": unique_asteroids,
"today_count": today_events.count(),
"today_already_have_map": today_already_have_map,
"total_maps_size": total_maps_size,
"week_count": this_week_count,
"next_week_count": next_week_count,
"month_count": this_month_count,
"next_month_count": next_month_count,
"maps_stats": maps_stats,
}
)

@action(detail=False, methods=["get"], permission_classes=(AllowAny,))
def highlights_maps_stats(self, request):

return Response(maps_folder_stats())

@action(detail=False, methods=["get"], permission_classes=(IsAuthenticated,))
def create_maps_for_today(self, request):
create_prediction_maps.delay()
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/components/AlertGenericError/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'
import Alert from '@mui/material/Alert'
import AlertTitle from '@mui/material/AlertTitle'

function AlertGenericError() {
return (
<Alert variant='outlined' severity='error'>
<AlertTitle>Opps, something went wrong</AlertTitle>
Server Error 500. We apologize for the inconvenience.
<br />
We are working to resolve the issue. Please attempt again shortly.
</Alert>
)
}

export default AlertGenericError
34 changes: 21 additions & 13 deletions frontend/src/components/MapsStats/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,46 @@ import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import CardHeader from '@mui/material/CardHeader'
import UsagePlot from './UsagePlot'
import { getOccultationHighlights } from '../../services/api/Occultation'
import Box from '@mui/material/Box'
import AlertGenericError from '../AlertGenericError/index'
import { getHighlightsMapsStats } from '../../services/api/Occultation'
import { useQuery } from 'react-query'
import Skeleton from '@mui/material/Skeleton'
import moment from 'moment'

export default function Mapsdata() {
const { data, isLoading } = useQuery({
queryKey: ['occultationHighlights'],
queryFn: getOccultationHighlights,
const { data, isLoading, isError } = useQuery({
queryKey: ['highlightsMapsStats'],
queryFn: getHighlightsMapsStats,
keepPreviousData: true,
refetchInterval: false,
refetchOnWindowFocus: false,
retry: false,
staleTime: 1 * 60 * 60 * 1000
})

if (isLoading) return <Skeleton variant='rectangular' width='100%' height={250} />

if (isError)
return (
<Box sx={{ height: 250 }}>
<AlertGenericError />
</Box>
)
return (
<Card sx={{ height: '100%', borderRadius: '10px' }}>
<CardHeader
title={isLoading ? <Skeleton animation='wave' /> : 'MAPS OVERVIEW'}
titleTypographyProps={{ variant: 'h6', fontSize: '1.0rem', color: '#4f4e4e' }}
/>
<Card sx={{ height: 250, borderRadius: '10px' }}>
<CardHeader title='MAPS OVERVIEW' titleTypographyProps={{ variant: 'h6', fontSize: '1.0rem', color: '#4f4e4e' }} />
<CardContent>
<Typography variant='h3' sx={{ fontWeight: 700, fontSize: '1.8rem', textAlign: 'left', paddingBottom: '20px', color: '#4dabf5' }}>
{isLoading ? <Skeleton /> : data?.maps_stats.total_count}
{data?.total_count}
</Typography>

<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Period:</strong> {isLoading ? <Skeleton /> : moment(data?.maps_stats.period[0]).utc().format('YYYY-MM-DD')} to{' '}
{moment(data?.maps_stats.period[1]).utc().format('YYYY-MM-DD')}
<strong>Period:</strong> {isLoading ? <Skeleton /> : moment(data?.period[0]).utc().format('YYYY-MM-DD')} to{' '}
{moment(data?.period[1]).utc().format('YYYY-MM-DD')}
</Typography>

{isLoading ? <></> : <UsagePlot maxSize={data?.maps_stats.folder_max_size} used={data?.maps_stats.total_size} />}
{!isLoading && <UsagePlot maxSize={data?.folder_max_size} used={data?.total_size} />}
</CardContent>
</Card>
)
Expand Down
43 changes: 23 additions & 20 deletions frontend/src/components/MonthlyForecast/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,41 @@ import CardContent from '@mui/material/CardContent'
import CardHeader from '@mui/material/CardHeader'
import Typography from '@mui/material/Typography'
import Skeleton from '@mui/material/Skeleton'
import Box from '@mui/material/Box'
import AlertGenericError from '../AlertGenericError/index'
import { useQuery } from 'react-query'
import { getOccultationHighlights } from '../../services/api/Occultation'
import { getHighlightsMonthlyForecast } from '../../services/api/Occultation'

function MonthlyForecast() {
const { data, isLoading } = useQuery({
queryKey: ['occultationHighlights'],
queryFn: getOccultationHighlights,
const { data, isLoading, isError } = useQuery({
queryKey: ['highlightsMonthlyForecast'],
queryFn: getHighlightsMonthlyForecast,
keepPreviousData: true,
refetchInterval: false,
refetchOnWindowFocus: false,
retry: false,
staleTime: 1 * 60 * 60 * 1000
})

if (isLoading) return <Skeleton variant='rectangular' width='100%' height={250} />

if (isError)
return (
<Box sx={{ height: 250 }}>
<AlertGenericError />
</Box>
)

return (
<Card sx={{ height: '100%', borderRadius: '10px' }}>
<Card sx={{ height: 250, borderRadius: '10px' }}>
<CardHeader title='UPCOMING THIS MONTH' titleTypographyProps={{ variant: 'h6', fontSize: '1.0rem', color: '#4f4e4e' }} />
<CardContent>
{isLoading ? (
<Skeleton variant='rectangular' width='100%' height={200} />
) : (
<>
<Typography
variant='h3'
sx={{ fontWeight: 700, fontSize: '1.8rem', textAlign: 'left', paddingBottom: '20px', color: '#4383cc' }}
>
{data?.month_count}
</Typography>
<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Next Month:</strong> {data?.next_month_count}
</Typography>
</>
)}
<Typography variant='h3' sx={{ fontWeight: 700, fontSize: '1.8rem', textAlign: 'left', paddingBottom: '20px', color: '#4383cc' }}>
{data?.month_count}
</Typography>
<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Next Month:</strong> {data?.next_month_count}
</Typography>
</CardContent>
</Card>
)
Expand Down
55 changes: 29 additions & 26 deletions frontend/src/components/UniqueAsteroids/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,48 @@ import CardContent from '@mui/material/CardContent'
import CardHeader from '@mui/material/CardHeader'
import Typography from '@mui/material/Typography'
import Skeleton from '@mui/material/Skeleton'
import Box from '@mui/material/Box'
import { useQuery } from 'react-query'
import { getOccultationHighlights } from '../../services/api/Occultation'
import { getHighlightsUniqueAsteroids } from '../../services/api/Occultation'
import moment from 'moment'
import AlertGenericError from '../AlertGenericError/index'

function UniqueAsteroids() {
const { data, isLoading } = useQuery({
queryKey: ['occultationHighlights'],
queryFn: getOccultationHighlights,
const { data, isLoading, isError } = useQuery({
queryKey: ['highlightsUniqueAsteroids'],
queryFn: getHighlightsUniqueAsteroids,
keepPreviousData: true,
refetchInterval: false,
refetchOnWindowFocus: false,
retry: false,
staleTime: 1 * 60 * 60 * 1000
})

if (isLoading) return <Skeleton variant='rectangular' width='100%' height={250} />

if (isError)
return (
<Box sx={{ height: 250 }}>
<AlertGenericError />
</Box>
)

return (
<Card sx={{ height: '100%', borderRadius: '10px' }}>
<Card sx={{ height: 250, borderRadius: '10px' }}>
<CardHeader title='TOTAL FORECAST' titleTypographyProps={{ variant: 'h6', fontSize: '1.0rem', color: '#4f4e4e' }} />
<CardContent>
{isLoading ? (
<Skeleton variant='rectangular' width='100%' height={200} />
) : (
<>
<Typography
variant='h3'
sx={{ fontWeight: 700, fontSize: '1.8rem', textAlign: 'left', paddingBottom: '20px', color: '#0e4686' }}
>
{data?.count}
</Typography>
<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Unique Asteroids:</strong> {data?.unique_asteroids}
</Typography>
<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Earliest:</strong> {moment(data?.earliest).utc().format('YYYY-MM-DD HH:mm:ss')} (UTC)
</Typography>
<Typography variant='body2' sx={{ margin: '0px 0', fontSize: '1rem' }}>
<strong>Latest:</strong> {moment(data?.latest).utc().format('YYYY-MM-DD HH:mm:ss')} (UTC)
</Typography>
</>
)}
<Typography variant='h3' sx={{ fontWeight: 700, fontSize: '1.8rem', textAlign: 'left', paddingBottom: '20px', color: '#0e4686' }}>
{data?.count}
</Typography>
<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Unique Asteroids:</strong> {data?.unique_asteroids}
</Typography>
<Typography variant='body2' sx={{ margin: '5px 0', fontSize: '1rem' }}>
<strong>Earliest:</strong> {moment(data?.earliest).utc().format('YYYY-MM-DD HH:mm:ss')} (UTC)
</Typography>
<Typography variant='body2' sx={{ margin: '0px 0', fontSize: '1rem' }}>
<strong>Latest:</strong> {moment(data?.latest).utc().format('YYYY-MM-DD HH:mm:ss')} (UTC)
</Typography>
</CardContent>
</Card>
)
Expand Down
Loading

0 comments on commit 8031697

Please sign in to comment.