Compare View

switch
from
...
to
 
Commits (7)
config/pyros_observatory/general/schemas/schema_observatory-2.0.yml
... ... @@ -539,8 +539,11 @@ schema;schema_UNIT:
539 539 home:
540 540 type: str
541 541 required: True
542   - duskelev:
543   - type: str
  542 + dusk_elev:
  543 + type: any
  544 + required: True
  545 + dawn_elev:
  546 + type: any
544 547 required: True
545 548 horizon:
546 549 type: map
... ...
pyros_api.py
... ... @@ -107,6 +107,9 @@ class PyrosAPI:
107 107 f"Server {self.host} doesn't respond. The website might be down.")
108 108 exit(1)
109 109 print(f"Request status code {request.status_code}")
  110 + if request.status_code == 401:
  111 + print("Bad token, disconnecting from webserver. Please authenticate yourself next time.")
  112 + self.delete_token()
110 113 return request.json()
111 114  
112 115 def get_sequences_for_period(self, start_date: str, end_date: str) -> dict:
... ... @@ -140,6 +143,11 @@ class PyrosAPI:
140 143 exit(1)
141 144 return response.content.decode("utf-8")
142 145  
  146 + def delete_token(self):
  147 + if os.path.exists("TOKEN"):
  148 + os.remove("TOKEN")
  149 + print("Token deleted")
  150 +
143 151  
144 152 @click.group()
145 153 @click.option('--host', '-h', help='host name (example: http://localhost:8000 or http://pyros.omp.eu) without last slash')
... ...
src/core/pyros_django/majordome/agent/Agent.py
... ... @@ -154,7 +154,7 @@ import config.old_config as config_old
154 154 #from config import *
155 155  
156 156 from majordome.models import AgentSurvey, AgentCmd, AgentLogs
157   -from user_mgmt.models import Period
  157 +from user_mgmt.models import Period, Institute, ScientificProgram, SP_Period
158 158 from scp_mgmt.models import Quota
159 159  
160 160 from vendor.guitastro.src.guitastro import Ephemeris
... ... @@ -3576,8 +3576,10 @@ class Agent:
3576 3576 d_prev = 0
3577 3577 d_cur = 0
3578 3578 d_total = 0
  3579 + dusk_elev1, dusk_elev2 = self.config.getDuskElev()
  3580 + dawn_elev1, dawn_elev2 = self.config.getDawnElev()
3579 3581 night_info = {}
3580   - self._duskelev = self.config.getDuskElev()
  3582 + _ ,self._duskelev = self.config.getDuskElev()
3581 3583 while jd < jd2:
3582 3584 night = self._oc['config'].fn.date2night(jd)
3583 3585 for target in targets:
... ... @@ -3586,13 +3588,15 @@ class Agent:
3586 3588 ks = np.where(ephem['alt'] < self._duskelev)
3587 3589 d_prev = d_prev + d_cur
3588 3590 d_cur = len(ks[0])
3589   - night_info[night] = [0, d_prev, d_cur, 0]
  3591 + _, start_index = self.get_indexes_of_night(ephem, dusk_elev1, dusk_elev2)
  3592 + night_info[night] = [0, d_prev, d_cur, 0, start_index]
  3593 +
3590 3594 jd += 1
3591 3595 d_total = d_prev + d_cur
3592 3596 for key, val in night_info.items():
3593 3597 night_id = key
3594 3598 val[0] = d_total
3595   - val[-1] = d_total - val[-2]
  3599 + val[-2] = d_total - val[-3]
3596 3600 # --- update db TODO
3597 3601 try:
3598 3602 if Quota.objects.get(night_id=night_id):
... ... @@ -3607,7 +3611,8 @@ class Agent:
3607 3611 quota_attributes["d_total"] = val[0]
3608 3612 quota_attributes["d_previous"] = val[1]
3609 3613 quota_attributes["d_current"] = val[2]
3610   - quota_attributes["d_next"] = val[-1]
  3614 + quota_attributes["d_next"] = val[3]
  3615 + quota_attributes["index_start"] = val[4]
3611 3616 quota.set_attributes_and_save(quota_attributes)
3612 3617 operiod.quota = Quota.objects.get(night_id=list(night_info.keys())[0], id_period=operiod.id)
3613 3618 operiod.save()
... ... @@ -3615,6 +3620,41 @@ class Agent:
3615 3620 #pickle.dump(night_info, open(filename, "wb"))
3616 3621 return night_info
3617 3622  
  3623 + def update_quota_institutes_and_sp_for_night(self, quota_night):
  3624 + for institute in Institute.objects.all():
  3625 + institute_new_quota = quota_night.convert_to_quota(institute.quota_f)
  3626 + institute.quota.set_attributes_and_save(institute_new_quota)
  3627 + for sp_period in SP_Period.objects.filter(scientific_program__in=institute.scientific_programs.all(), period=Period.objects.get(id=quota_night.id_period)):
  3628 + sp_new_quota = institute.quota.convert_to_quota(sp_period.quota_f)
  3629 +
  3630 + sp_period.quota.set_attributes_and_save(sp_new_quota)
  3631 +
  3632 + def get_indexes_of_night(self, ephemeris:dict, dusk_elev1:int, dusk_elev2:int)->Tuple:
  3633 + es = ephemeris["alt"]
  3634 + delta_w = dusk_elev2 - dusk_elev1
  3635 + delta_es = es[1:] - es[:-1]
  3636 + delta_es = np.append(delta_es, delta_es[-1])
  3637 + ks = np.linspace(0, 86400, 86401)
  3638 + k1 = -1
  3639 + k2 = -1
  3640 + k = 0
  3641 + if delta_w > 0:
  3642 + for e, delta_e, k in zip(es, delta_es, ks):
  3643 + if e > dusk_elev1 and k1 == -1 and delta_e > 0:
  3644 + k1 = k
  3645 + elif e > dusk_elev2 and k2 == -1 and delta_e > 0:
  3646 + k2=k
  3647 + break
  3648 + else:
  3649 + for e, delta_e, k in zip(es, delta_es, ks):
  3650 +
  3651 + if e < dusk_elev1 and k1 == -1 and delta_e < 0:
  3652 + k1=k
  3653 + elif e < dusk_elev2 and k2 == -1 and delta_e < 0:
  3654 + k2=k
  3655 + break
  3656 +
  3657 + return (k1, k2)
3618 3658 """
3619 3659 =================================================================
3620 3660 MAIN
... ...
src/core/pyros_django/misc/fixtures/initial_fixture_dev_TZ.json
... ... @@ -3,8 +3,7 @@
3 3 "pk": 1,
4 4 "fields": {
5 5 "name": "France",
6   - "desc": "",
7   - "quota": null
  6 + "desc": ""
8 7 }
9 8 },
10 9 {
... ... @@ -211,7 +210,7 @@
211 210 "description_long": "",
212 211 "sp_pi": 2,
213 212 "science_theme": 1,
214   - "quota_f":0.9,
  213 +
215 214 "is_auto_validated": true
216 215 }
217 216 },
... ... @@ -225,7 +224,7 @@
225 224 "description_long": "",
226 225 "sp_pi": 2,
227 226 "science_theme": 1,
228   - "quota_f":0.1,
  227 +
229 228 "is_auto_validated": true
230 229 }
231 230 },
... ... @@ -239,7 +238,7 @@
239 238 "description_long": "",
240 239 "sp_pi": 5,
241 240 "science_theme": 1,
242   - "quota_f": "0.7",
  241 +
243 242 "is_auto_validated": true
244 243 }
245 244 },
... ... @@ -253,7 +252,7 @@
253 252 "description_long": "",
254 253 "sp_pi": 5,
255 254 "science_theme": 1,
256   - "quota_f": "0.3",
  255 +
257 256 "is_auto_validated": true
258 257 }
259 258 },
... ... @@ -265,7 +264,9 @@
265 264 "scientific_program": 1,
266 265 "status": "Accepted",
267 266 "public_visibility": "Name",
268   - "is_valid": "Accepted"
  267 + "is_valid": "Accepted",
  268 + "quota_f":0.9,
  269 + "priority": 90
269 270 }
270 271 },
271 272 {
... ... @@ -276,7 +277,9 @@
276 277 "scientific_program": 3,
277 278 "status": "Accepted",
278 279 "public_visibility": "Name",
279   - "is_valid": "Accepted"
  280 + "is_valid": "Accepted",
  281 + "quota_f":0.1,
  282 + "priority":20
280 283 }
281 284 },
282 285 {
... ... @@ -287,7 +290,9 @@
287 290 "scientific_program": 4,
288 291 "status": "Accepted",
289 292 "public_visibility": "Name",
290   - "is_valid": "Accepted"
  293 + "is_valid": "Accepted",
  294 + "quota_f": "0.3",
  295 + "priority": 40
291 296 }
292 297 },
293 298 {
... ... @@ -298,7 +303,9 @@
298 303 "scientific_program": 2,
299 304 "status": "Accepted",
300 305 "public_visibility": "Name",
301   - "is_valid": "Accepted"
  306 + "is_valid": "Accepted",
  307 + "quota_f": "0.7",
  308 + "priority": 60
302 309 }
303 310 },
304 311 {
... ...
src/core/pyros_django/obs_config/obsconfig_class.py
... ... @@ -10,6 +10,8 @@ import socket
10 10 from datetime import datetime
11 11 from pykwalify.errors import PyKwalifyException, SchemaError
12 12 from pathlib import Path
  13 +import ast
  14 +
13 15  
14 16 sys.path.append(os.environ.get("PROJECT_ROOT_PATH", os.path.join(os.getcwd(),"../../../../")))
15 17 from vendor.guitastro.src.guitastro import FileNames, Home
... ... @@ -1242,13 +1244,24 @@ class OBSConfig:
1242 1244  
1243 1245 def getDuskElev(self)->float:
1244 1246 """
1245   - Return duskelev of current unit
  1247 + Return dusk_elev of current unit
1246 1248  
1247 1249 Returns:
1248   - float: string reprensenting duskelev of unit
  1250 + Tuple: string reprensenting dusk_elev of unit
  1251 + """
  1252 + dusk_elev = ast.literal_eval(self.get_unit_by_name(self.unit_name).get("dusk_elev"))
  1253 + return dusk_elev
  1254 +
  1255 + def getDawnElev(self)->float:
1249 1256 """
1250   - duskelev = float(self.get_unit_by_name(self.unit_name).get("duskelev"))
1251   - return duskelev
  1257 + Return dawn_elev of current unit
  1258 +
  1259 + Returns:
  1260 + Tuple: string reprensenting dusk_elev of unit
  1261 + """
  1262 + dawn_elev = ast.literal_eval(self.get_unit_by_name(self.unit_name).get("dawn_elev"))
  1263 + return dawn_elev
  1264 +
1252 1265  
1253 1266 def get_agent_path_data_root(self, agent_name:str, computer_hostname=None) -> str:
1254 1267 """
... ...
src/core/pyros_django/scheduling/A_Scheduler.py
... ... @@ -232,6 +232,7 @@ class A_Scheduler(Agent):
232 232  
233 233 def update_db_quota_sequence(self, sequence_id, quota_attributes):
234 234 sequence = Sequence.objects.get(id=sequence_id)
  235 +
235 236 new_quota = Quota()
236 237 new_quota.set_attributes_and_save(quota_attributes)
237 238 sequence.quota = new_quota
... ... @@ -291,7 +292,21 @@ class A_Scheduler(Agent):
291 292 # --- Unpack the matrix to effective schedule arrays
292 293 schedule_eff_jd, schedule_eff_binary, schedule_eff_sequence_id, schedule_eff_scientific_programm_id, schedule_eff_order, schedule_eff_visibility = input_matrix
293 294 # --- Get the index of the current instant in the night
294   - nownight, index = self._fn.date2night("now", self.BINS_NIGHT)
  295 + date = guitastro.Date("now") + "12H"
  296 + nownight, index = self._fn.date2night(date.iso(), self.BINS_NIGHT)
  297 + index_stop = oquota.index_start + oquota.d_current
  298 + #print(f"{index=} {index_stop=} {oquota.index_start=}")
  299 + if index > index_stop:
  300 + period_quota_passed = oquota.d_current
  301 + elif index > oquota.index_start:
  302 + period_quota_passed = index - oquota.index_start
  303 + else:
  304 + period_quota_passed = 0
  305 + oquota.d_passed = period_quota_passed
  306 + period_quota_to_schedule = oquota.d_current - period_quota_passed
  307 + oquota.d_schedule = period_quota_to_schedule
  308 + oquota.save()
  309 + self.update_quota_institutes_and_sp_for_night(oquota)
295 310 self.dprint(f"{nownight=} {index=}")
296 311 # --- Add all ever observed sequences from 0 to index
297 312 if nownight == night and (index >= 0 or index < self.BINS_NIGHT):
... ... @@ -309,6 +324,24 @@ class A_Scheduler(Agent):
309 324 print(f"Invalid entry in the database")
310 325 #print(f"{schedule_jd=}")
311 326  
  327 + # Set global quota for SP and institutes for current night
  328 + date = guitastro.Date("now") + "240H"
  329 + nownight, index = self._fn.date2night(date.iso(), self.BINS_NIGHT)
  330 + index_stop = oquota.index_start + oquota.d_current
  331 + #print(f"{index=} {index_stop=} {oquota.index_start=}")
  332 + if index > index_stop:
  333 + period_quota_passed = oquota.d_current
  334 + elif index > oquota.index_start:
  335 + period_quota_passed = index - oquota.index_start
  336 + else:
  337 + period_quota_passed = 0
  338 + oquota.d_passed = period_quota_passed
  339 + period_quota_to_schedule = oquota.d_current - period_quota_passed
  340 + oquota.d_schedule = period_quota_to_schedule
  341 + oquota.save()
  342 + self.update_quota_institutes_and_sp_for_night(oquota)
  343 +
  344 +
312 345 # ===================================================================
313 346 # --- Loop over the sequences of the night to extract useful infos
314 347 # ===================================================================
... ... @@ -389,29 +422,18 @@ class A_Scheduler(Agent):
389 422 self.dprint(f"{scientific_program_ids=}")
390 423 for scientific_program_id in scientific_program_ids:
391 424 scientific_program_info = {}
392   - try:
393   - osp = ScientificProgram.objects.get(id=scientific_program_id)
394   - # --- ospperiod is the SP object
395   - ospperiod = SP_Period.objects.get(period = period_id, scientific_program = osp)
396   - scientific_program_info['priority'] = ospperiod.priority
397   - scientific_program_info['over_quota_duration'] = ospperiod.over_quota_duration
398   - scientific_program_info['over_quota_duration_allocated'] = ospperiod.over_quota_duration_allocated
399   - scientific_program_info['over_quota_duration_remaining'] = ospperiod.over_quota_duration_remaining
400   - scientific_program_info['quota_allocated'] = ospperiod.quota_allocated
401   - scientific_program_info['quota_minimal'] = ospperiod.quota_minimal
402   - scientific_program_info['quota_nominal'] = ospperiod.quota_nominal
403   - scientific_program_info['quota_remaining'] = ospperiod.quota_remaining
404   - scientific_program_info['token_allocated'] = ospperiod.token_allocated
405   - scientific_program_info['token_remaining'] = ospperiod.token_allocated
406   - except:
407   - # --- simulation
408   - scientific_program_info['priority'] = 0
409   - if scientific_program_info['priority'] == 0:
410   - # --- simulation
411   - priority = 50 + scientific_program_id*5
412   - scientific_program_info['priority'] = priority
413   - scientific_program_info['quota_allocated'] = 12000
414   - scientific_program_info['quota_remaining'] = 12000
  425 + ospperiod = SP_Period.objects.get(scientific_program=ScientificProgram.objects.get(id=scientific_program_id), period=info["operiod"])
  426 + # --- ospperiod is the SP object
  427 + scientific_program_info['priority'] =ospperiod.priority
  428 + quota_ospperiod = ospperiod.quota
  429 + # example to get d_current of sp_period
  430 + # quota_ospperiod.d_current
  431 + scientific_program_info['token_allocated'] = ospperiod.token_allocated
  432 + scientific_program_info['token_remaining'] = ospperiod.token_allocated
  433 + scientific_program_info['quota_allocated'] = quota_ospperiod.d_current
  434 + scientific_program_info['quota_remaining'] = quota_ospperiod.d_schedule
  435 + scientific_program_info['d_currentq'] = 0
  436 +
415 437 scientific_program_infos[str(scientific_program_id)] = scientific_program_info
416 438 self.dprint(f"{scientific_program_id=} priority={scientific_program_info['priority']} quota={scientific_program_info['quota_remaining']}")
417 439  
... ... @@ -530,7 +552,28 @@ class A_Scheduler(Agent):
530 552 # --- Update the scientific program dict
531 553 quota_remaining -= duration
532 554 scientific_program_infos[str(scientific_program_id)]['quota_remaining'] = quota_remaining
533   -
  555 +
  556 + # --- Update the DB
  557 + osequence = Sequence.objects.get(id=sequence_id)
  558 + sequence_quota = osequence.quota
  559 + sequence_quota.d_schedule = 0
  560 + sequence_quota.d_currentq = duration
  561 + sequence_quota.d_scheduleq = duration
  562 + osequence.quota.save()
  563 + # quota_ospperiod.d_currentq += duration
  564 + # quota_ospperiod.save()
  565 + scientific_program_infos[str(scientific_program_id)]['d_currentq'] += duration
  566 +
  567 + for scientific_program_id in scientific_program_ids:
  568 + ospperiod = SP_Period.objects.get(scientific_program=ScientificProgram.objects.get(id=scientific_program_id), period=info["operiod"])
  569 + quota_ospperiod = ospperiod.quota
  570 + quota_ospperiod.d_currentq = scientific_program_infos[str(scientific_program_id)]['d_currentq']
  571 + quota_ospperiod.d_scheduleq = scientific_program_infos[str(scientific_program_id)]['d_currentq']
  572 + ospperiod.quota.save()
  573 + # for sp in SP_Period.objects.filter(period=Period.objects.get(id=period_id)):
  574 + # institute_quota = sp.scientific_program.institute.quota
  575 + # institute_quota.d_currentq += sp.quota.d_currentq
  576 + # sp.scientific_program.institute.save()
534 577  
535 578 # ===================================================================
536 579 # --- Insert sequences in the schedule. Respecting priority but over quota
... ... @@ -632,7 +675,7 @@ class A_Scheduler(Agent):
632 675 #start_expo_pref = "BESTELEV" #"IMMEDIATE"
633 676 start_expo_pref = 0 # for bestelev 1, for immediate 0
634 677 start_date,_ = self._fn.night2date(info["night"])
635   - start_date = start_date + 0.25 + (0.5*k)
  678 + start_date = start_date + 0.25 + (0.05*k)
636 679 start_date_to_datetime = guitastro.Date(start_date).iso()
637 680 #start_date = datetime.datetime(2023, 6, 28, 10, 21, 40)
638 681 #end_date = datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc)
... ...
src/core/pyros_django/scp_mgmt/A_SCP_Manager.py
... ... @@ -287,12 +287,12 @@ class A_SCP_Manager(Agent):
287 287 institute = sp.institute
288 288 institute_quota = institute.quota
289 289 new_quota = Quota()
290   - quota_attributes = institute_quota.convert_to_quota(sp.quota_f)
  290 + quota_attributes = institute_quota.convert_to_quota(sp_period.quota_f)
291 291 quota_attributes["night_id"] = 1
292 292 quota_attributes["id_period"] = id_period
293 293 new_quota.set_attributes_and_save(quota_attributes)
294   - sp.quota = new_quota
295   - sp.save()
  294 + sp_period.quota = new_quota
  295 + sp_period.save()
296 296  
297 297 except Exception as e:
298 298 print(e)
... ...
src/core/pyros_django/scp_mgmt/models.py
... ... @@ -4,6 +4,9 @@ from django.db import models
4 4 class Quota(models.Model):
5 5 id_period = models.BigIntegerField(blank=True, null=True)
6 6 night_id = models.CharField(max_length=8, null=True, blank=True, db_index=True)
  7 +
  8 + # in seconds
  9 + index_start = models.BigIntegerField(default=0, blank=True, null=True)
7 10 d_total = models.BigIntegerField(default=0, blank=True, null=True)
8 11 d_totalq = models.BigIntegerField(default=0, blank=True, null=True)
9 12 d_totalx = models.BigIntegerField(default=0, blank=True, null=True)
... ... @@ -57,6 +60,9 @@ class Quota(models.Model):
57 60 self.id_period = quota_attributes["id_period"]
58 61 if quota_attributes.get("night_id") != None:
59 62 self.night_id = quota_attributes["night_id"]
  63 +
  64 + if quota_attributes.get("index_start") != None:
  65 + self.index_start = quota_attributes.get("index_start")
60 66  
61 67 if quota_attributes.get("d_totalq") != None:
62 68 self.d_totalq = quota_attributes["d_totalq"]
... ...
src/core/pyros_django/scp_mgmt/templates/scp_mgmt/quota_sp.html
... ... @@ -91,9 +91,9 @@
91 91 <td>{{institute.quota.d_nextq}}</td>
92 92 <td>{{institute.quota.d_nextx}}</td>
93 93 </tr>
94   - {% for sp in institute.scientific_programs.all %}
  94 + {% for sp in sp_periods_per_institute|get_item:institute.name %}
95 95 <tr class="sp">
96   - <td>Scientific program: {{sp.name}} </td>
  96 + <td>Scientific program: {{sp.scientific_program.name}} </td>
97 97 <td>{{sp.quota_f}} </td>
98 98 <td> <b>{{sp.quota.d_total}}</b> </td>
99 99 <td>{{sp.quota.d_totalq}}</td>
... ... @@ -119,6 +119,35 @@
119 119 <td>{{sp.quota.d_nextq}}</td>
120 120 <td>{{sp.quota.d_nextx}}</td>
121 121 </tr>
  122 + {% for sequence in sequences|get_item:sp.scientific_program.name %}
  123 + <tr class="sequence">
  124 + <td> Sequence: {{sequence.name}} </td>
  125 + <td> </td>
  126 + <td> <b>{{sequence.quota.d_total}}</b> </td>
  127 + <td>{{sequence.quota.d_totalq}}</td>
  128 + <td>{{sequence.quota.d_totalx}}</td>
  129 +
  130 + <td> <b>{{sequence.quota.d_previous}}</b> </td>
  131 + <td>{{sequence.quota.d_previousq}}</td>
  132 + <td>{{sequence.quota.d_previousx}}</td>
  133 +
  134 + <td> <b>{{sequence.quota.d_current}}</b> </td>
  135 + <td>{{sequence.quota.d_currentq}}</td>
  136 + <td>{{sequence.quota.d_currentx}}</td>
  137 +
  138 + <td> <b>{{sequence.quota.d_passed}}</b> </td>
  139 + <td>{{sequence.quota.d_passedq}}</td>
  140 + <td>{{sequence.quota.d_passedx}}</td>
  141 +
  142 + <td> <b>{{sequence.quota.d_schedule}}</b> </td>
  143 + <td>{{sequence.quota.d_scheduleq}}</td>
  144 + <td>{{sequence.quota.d_schedulex}} </td>
  145 +
  146 + <td> <b>{{sequence.quota.d_next}}</b> </td>
  147 + <td>{{sequence.quota.d_nextq}}</td>
  148 + <td>{{sequence.quota.d_nextx}}</td>
  149 + </tr>
  150 + {% endfor %}
122 151 {% endfor %}
123 152  
124 153 {% endfor %}
... ...
src/core/pyros_django/scp_mgmt/views.py
... ... @@ -21,7 +21,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
21 21 # Project imports
22 22 from dashboard.config_pyros import ConfigPyros
23 23 from .functions import get_global_svg_timeline, get_svg_timeline, get_proposal_svg_timeline
24   -from user_mgmt.models import ScientificProgram, Institute, Period, SP_Period_User, SP_Period, PyrosUser, SP_Period_Guest, ScienceTheme #, UserLevel
  24 +from user_mgmt.models import ScientificProgram, Institute, Period, SP_Period_User, SP_Period, PyrosUser, SP_Period_Guest, ScienceTheme, UserLevel #, UserLevel
25 25 from seq_submit.models import Sequence, Quota
26 26 #from src.core.pyros_django import scientific_program
27 27 from .forms import PeriodForm, ScienceThemeForm, ScientificProgramForm, InstituteForm, SP_PeriodForm,TACAssociationForm
... ... @@ -810,11 +810,31 @@ def institute_list(request):
810 810 @login_required
811 811 @level_required("Admin", "Unit-PI", "Observer", "Operator", "TAC", "Management board member")
812 812 def quota_sp(request):
813   - institutes = Institute.objects.all()
814   - scientific_programs = ScientificProgram.objects.all()
815 813 config = OBSConfig(os.environ["PATH_TO_OBSCONF_FILE"],os.environ["unit_name"])
  814 + CAN_VIEW_ALL_QUOTA = request.session.get("role") in ("Admin", "Unit-PI", "Unit-board", "Management board member")
816 815 current_night = config.fn.date2night("now")
817 816 current_period = Period.objects.exploitation_period()
  817 + sp_periods_per_institute = {}
  818 + if CAN_VIEW_ALL_QUOTA:
  819 + institutes = Institute.objects.all()
  820 + sp_period = SP_Period.objects.filter(period=current_period)
  821 + else:
  822 + user_sp = request.user.get_scientific_programs()
  823 + sp_period = SP_Period.objects.filter(scientific_program__in=user_sp, period=current_period)
  824 + institutes = []
  825 + # regroup sp_period per institute
  826 + for sp in sp_period:
  827 + if sp_periods_per_institute.get(sp.scientific_program.institute.name) is None:
  828 + sp_periods_per_institute[sp.scientific_program.institute.name] = []
  829 + if sp not in sp_periods_per_institute.get(sp.scientific_program.institute.name):
  830 + sp_periods_per_institute[sp.scientific_program.institute.name].append(sp)
  831 + sequences = {}
  832 + # regroup institutes and regroup sequence per scientific_program
  833 + for institute, sp_list in sp_periods_per_institute.items():
  834 + if not CAN_VIEW_ALL_QUOTA and institute not in institutes:
  835 + institutes.append(Institute.objects.get(name=institute))
  836 + for sp_period in sp_list:
  837 + sequences[sp_period.scientific_program.name] = sp_period.scientific_program.sequences.all()
818 838 # lowest id is period line
819 839 quota_current_night = Quota.objects.filter(id_period=current_period.id, night_id=current_night).order_by("id").first()
820 840 return render(request, 'scp_mgmt/quota_sp.html', locals())
... ...
src/core/pyros_django/seq_submit/functions.py
... ... @@ -481,7 +481,7 @@ def create_sequence_pickle(sequence):
481 481 eph = guitastro.Ephemeris()
482 482 eph.set_home(config.getHome())
483 483 # duskelev a parametrer dans obsconfig (yml)
484   - duskelev = -7
  484 + _, duskelev = config.getDuskElev()
485 485 errors = []
486 486 try:
487 487 #fullseq_dict["ephem"] = eph.target2night(fullseq_dict["sequence"]["config_attributes"]["target"], sequence.night_id, None, None, preferance=sequence.start_expo_pref, duskelev=duskelev)
... ...
src/core/pyros_django/seq_submit/validators.py
... ... @@ -109,7 +109,7 @@ def check_sequence_validity(seq):
109 109 guitastro_home = guitastro.Home(home)
110 110 fn.longitude = guitastro_home.longitude
111 111 seq.night_id = fn.get_night(seq.start_date.isoformat()[:19])
112   - duskelev = -7
  112 + _, duskelev = config.getDuskElev()
113 113 try:
114 114 # TODO remplacer les none par les fichiers pickle de ephem_sun & ephem_moon
115 115 # On a besoin de calculer la visibilité de l'objet donc il faut l'ephemeride
... ...
src/core/pyros_django/seq_submit/views.py
... ... @@ -305,7 +305,7 @@ def sequence_validate(request, seq_id):
305 305 eph = guitastro.Ephemeris()
306 306 eph.set_home(home)
307 307 # duskelev a parametrer dans obsconfig (yml)
308   - duskelev = -7
  308 + _, duskelev = config.getDuskElev()
309 309 message = ""
310 310 try:
311 311 # TODO remplacer les none par les fichiers pickle de ephem_sun & ephem_moon
... ...
src/core/pyros_django/user_mgmt/models.py
... ... @@ -70,7 +70,6 @@ class UserLevel(models.Model):
70 70 class Country(models.Model):
71 71 name = models.CharField(max_length=45, blank=True, null=True)
72 72 desc = models.TextField(blank=True, null=True)
73   - quota = models.FloatField(blank=True, null=True)
74 73  
75 74 class Meta:
76 75 managed = True
... ... @@ -86,7 +85,7 @@ class Institute(models.Model):
86 85 # fraction quota
87 86 quota_f = models.FloatField(
88 87 validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True)
89   -
  88 + country = models.ForeignKey(Country, on_delete=models.SET_NULL,related_name="institute_countrys", blank=True, null=True)
90 89 quota = models.ForeignKey(Quota, on_delete=models.SET_NULL,related_name="institute_quotas", blank=True, null=True)
91 90 #representative_user = models.ForeignKey("PyrosUser", on_delete=models.DO_NOTHING,related_name="institutes",default=1)
92 91  
... ... @@ -475,9 +474,7 @@ class ScientificProgram(models.Model):
475 474 science_theme = models.ForeignKey(ScienceTheme, on_delete=models.DO_NOTHING, related_name="scientific_program_theme", default=1)
476 475 is_auto_validated = models.BooleanField(default=False)
477 476 objects = ScientificProgramManager()
478   - quota = models.ForeignKey(Quota, on_delete=models.SET_NULL, related_name="scientific_program_quotas", blank=True, null=True)
479   - quota_f = models.FloatField(
480   - validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True)
  477 +
481 478  
482 479 class Meta:
483 480 managed = True
... ... @@ -541,6 +538,9 @@ class SP_Period(models.Model):
541 538 token = models.PositiveIntegerField(default=0)
542 539 token_allocated = models.PositiveIntegerField(default=0, blank=True)
543 540 token_remaining = models.PositiveIntegerField(default=0, blank=True)
  541 + quota = models.ForeignKey(Quota, on_delete=models.SET_NULL, related_name="sp_period_quotas", blank=True, null=True)
  542 + quota_f = models.FloatField(
  543 + validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True)
544 544 # Unit PI donne un nombre de priorité (100 = alert)
545 545 priority = models.IntegerField(
546 546 validators=[MinValueValidator(0), MaxValueValidator(100)], blank=True, null=True)
... ...