def remainingTime(self): "From this proposal's project's time accounting." if self.dss_project is not None: ta = TimeAccounting() return ta.getTimeLeft(self.dss_project) else: return None
def getTime(self, type): "Leverage time accounting for this proposal's project." if self.dss_project is not None: ta = TimeAccounting() return ta.getTime(type, self.dss_project) else: return None
def remainingTime(self): "From this session's dss sessions's time accounting." if self.dss_session is not None: ta = TimeAccounting() return ta.getTimeLeft(self.dss_session) else: return None
def dssAllocatedTime(self): "How much was the corresponding DSS project allocated?" if self.dss_project is not None: ta = TimeAccounting() return ta.getProjectTotalTime(self.dss_project) else: return None
def setUp(self): super(TestProposal, self).setUp() # this project has no allotments! self.project = DSSProject.objects.order_by('pcode').all()[0] # setup some periods self.start = datetime(2000, 1, 1, 0) self.end = self.start + timedelta(hours = 12) times = [(datetime(2000, 1, 1, 0), 5.0, "one") , (datetime(2000, 1, 1, 5), 3.0, "two") , (datetime(2000, 1, 1, 8), 4.0, "three") ] self.ps = [] state = DSSPeriod_State.objects.get(abbreviation = 'P') for start, dur, name in times: # each session has grade 4, time = 3 s = create_sesshun() s.name = name s.save() pa = DSSPeriod_Accounting(scheduled = dur) pa.save() p = DSSPeriod( session = s , start = start , duration = dur , state = state , accounting = pa ) p.save() self.ps.append(p) # Okay, now set up the corresponding proposal now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") sqlResult = { 'PROP_ID' : self.project.pcode , 'PROPOSAL_TYPE' : 'Regular' , 'STATUS' : 'Draft' , 'SUBMITTED_DATE' : now , 'CREATED_DATE' : now , 'MODIFIED_DATE' : now , 'TITLE' : 'Lynrd Sknyrd' , 'ABSTRACT' : 'What song do you wanna hear?' , 'proposal_id' : 0 , 'JOINT_PROPOSAL_TYPE' : 'Not a joint Proposal' } proposal = Proposal.createFromSqlResult(sqlResult) proposal.dss_project = self.project proposal.setSemester(self.project.semester.semester) proposal.save() self.proposal = proposal self.ta = TimeAccounting()
def GenerateReport(): ta = TimeAccounting() ui = UserInfoTools() outfile = open("./DssDbHealthReport.txt",'w') projects = sorted(Project.objects.all(), lambda x, y: cmp(x.pcode, y.pcode)) sessions = sorted(Sesshun.objects.all(), lambda x, y: cmp(x.name, y.name)) periods = Period.objects.exclude(state__name = 'Deleted').order_by('start') rcvrs = Receiver.objects.order_by("freq_low") deleted = Period_State.get_state('D') outfile.write("Projects without sessions:") values = [p.pcode for p in projects if len(p.sesshun_set.all()) == 0] print_values(outfile, values) outfile.write("\n\nSessions without a project:") values = [s.name for s in sessions if not s.project] print_values(outfile, values) outfile.write("\n\nOpen sessions (not completed) with alloted time < min duration:") values = [s.name for s in sessions \ if s.session_type.type == "open" and \ not s.status.complete and \ s.allotment.total_time < s.min_duration] print_values(outfile, values) outfile.write("\n\nOpen sessions (not completed) with time left < min duration:") values = [s.name for s in sessions \ if s.session_type.type == "open" and \ not s.status.complete and \ ta.getTimeLeft(s) < s.min_duration] print_values(outfile, values) outfile.write("\n\nOpen sessions with max duration < min duration:") values = [s.name for s in sessions \ if s.session_type.type == "open" and \ s.min_duration > s.max_duration] print_values(outfile, values) outfile.write("\n\nSessions with min duration too small:") ss1 = [s for s in sessions if s.min_duration <= 0.25] ss = sorted(ss1, lambda x, y: cmp(x.min_duration, y.min_duration)) values = ["%s, %f" % (s.name, s.min_duration) for s in ss] print_values(outfile, values) outfile.write("\n\nSessions with negative observed time:") values = ["%s; obs: %s, total: %s" % \ (s.name, str(ta.getTime("observed", s)), str(s.allotment.total_time)) \ for s in sessions if ta.getTime("observed", s) < 0.0] print_values(outfile, values) outfile.write("\n\nSessions without receivers:") values = [s.name for s in sessions \ if len(s.receiver_list()) == 0 and \ s.project.pcode not in ("Maintenance", "Shutdown")] print_values(outfile, values) outfile.write("\n\nOpen sessions with default frequency 0:") values = [s.name for s in sessions \ if s.session_type.type == "open" and s.frequency == 0.0] print_values(outfile, values) outfile.write("\n\nSessions with invalid LST Exclusion/Inclusion parameters:") values = invalidLSTParameters(sessions) print_values(outfile, values) outfile.write("\n\nSessions with repeated observing parameters:") values = repeatedObservingParameters(sessions) print_values(outfile, values) #outfile.write("\n\nSessions with unmatched observer parameter pairs:") #values = [s.name for s in missing_observer_parameter_pairs(sessions)] #print_values(outfile, values) outfile.write("\n\nSessions with RA and Dec equal to zero:") values = [s.name for s in sessions \ if s.getTarget() is not None and s.target.vertical == 0.0 \ and s.target.horizontal == 0.0] print_values(outfile, values) outfile.write("\n\nSessions with frequency (GHz) out of all Rcvr bands") values = [] for s in sessions: out_of_band = False # freq. must be out of band for ALL rcvrs to be reported rcvrs = [Receiver.objects.get(abbreviation = rname) \ for rname in s.rcvrs_specified()] in_bands = [r for r in rcvrs if r.in_band(s.frequency)] # don't report sessions w/ out rcvrs: we do that above if len(in_bands) == 0 and len(rcvrs) != 0: values.append("%s %s %5.4f" % (s.name , s.receiver_list_simple() , s.frequency)) print_values(outfile, values) outfile.write("\n\nUpcoming Windowed, Elective, and Fixed Sessions that are not enabled:") sa = SessionInActiveAlerts() print_values(outfile , ["%s session %s which runs %s" % (u.session.session_type.type , u.session.id , sa.getRange(u)) for u in sa.findDisabledSessionAlerts()] ) outfile.write("\n\nUpcoming Windowed, Elective, and Fixed Sessions that are not authorized:") sa = SessionInActiveAlerts() print_values(outfile , ["%s session %s which runs %s" % (u.session.session_type.type , u.session.id , sa.getRange(u)) for u in sa.findUnauthorizedSessionAlerts()] ) outfile.write("\n\nProjects without a friend:") values = [p.pcode for p in projects if not p.complete and len(p.friend_set.all()) == 0] print_values(outfile, values) outfile.write("\n\nProjects without any schedulable sessions:") values = [p.pcode for p in projects \ if not p.complete and \ not any([s.schedulable() for s in p.sesshun_set.all()])] print_values(outfile, values) outfile.write("\n\nProjects without any observers:") values = [p.pcode for p in projects \ if not p.complete and len(p.get_observers()) == 0] print_values(outfile, values) outfile.write("\n\nProjects whose project type is inconsistent with its sessions' observing types:") values = [p.pcode for p in projects \ if p.is_science() and \ not all([s.isScience() for s in p.sesshun_set.all()])] print_values(outfile, values) outfile.write("\n\nProjects whose category is inconsistent with its sessions' categories:") badCats = [] for p in projects: cats = list(set([s.getCategory() for s in p.sesshun_set.all()])) if len(cats) > 1: badCats.append(p.pcode) elif len(cats) == 1 and cats[0] != p.get_category(): badCats.append(p.pcode) print_values(outfile, badCats) outfile.write("\n\nReceiver changes happening on days other than maintenance days:") values = [str(s) for s in check_maintenance_and_rcvrs()] print_values(outfile, values) outfile.write("\n\nPeriods longer then 24 hours:") values = Period.objects.filter(duration__gt = 24.0) print_values(outfile, values) outfile.write("\n\nPeriods in the future whose receivers are different then their sessions.") fps = Period.objects.filter(start__gt = datetime.now()).order_by('start') # Here we compare what the period currently has, with the function that # the period was initialized with bps = [p for p in fps if p.receiver_list_simple() != ", ".join(p.session.rcvrs_specified())] values = ["%s at %s; %s vs. %s" % (p.session.name , p.start , p.receiver_list_simple() , ", ".join(p.session.rcvrs_specified())) \ for p in bps] print_values(outfile, values) outfile.write("\n\nPeriods which have been observed when none of their receivers were up:") start = datetime(2009, 10, 10) # don't bother looking before this end = datetime.utcnow() - timedelta(days=1) # leave a day buffer obs_ps = [p for p in periods if p.start > start and p.start < end \ and p.session.name not in ['Shutdown', 'Maintenance'] \ and p.state != deleted] bad_ps = [p for p in obs_ps if not p.has_observed_rcvrs_in_schedule()] values = ["%s, %s" % (p.__str__(), p.receiver_list()) for p in bad_ps] print_values(outfile, values) outfile.write("\n\nSessions for which periods are scheduled when none of their receivers are up:") now = datetime.utcnow() future_ps = [p for p in periods if p.start > now \ and p.session.project.pcode not in ['Shutdown', 'Maintenance']] bad_ps = [p for p in future_ps if not p.has_required_receivers()] values = ["%s, %s" % (p.__str__(), p.session.receiver_list_simple()) \ for p in bad_ps] print_values(outfile, values) # note that here we use the session's rcvrs, *not* the periods' # rcvrs because we are looking into the future. outfile.write("\n\nPeriods in the future that are using retired hardware:") values = [p for p in periods if p.state != deleted and p.start > now and p.session.usesDeletedReceiver()] print_values(outfile, values) outfile.write("\n\nProjects that contain non-unique session names:") names = [(p.pcode, [s.name for s in p.sesshun_set.all()]) for p in projects] values = [p for p, n in names if len(set(n)) != len(n)] print_values(outfile, values) outfile.write("\n\nUsers with duplicate accounts by name:") values = ui.findUsersWithSameNames() print_values(outfile, values) outfile.write("\n\nUsers with shared PST accounts:\n") sharedPstIds = ui.findUsersWithSamePstId(quiet = True) # print out useful format if len(sharedPstIds) > 0: for pst_id, us in sharedPstIds: outfile.write("PST ID: %s\n" % pst_id) for u in us: outfile.write(" %s, %d\n" % (u, u.id)) outfile.write(" Projects: %s\n" % u.getProjects()) outfile.write(" Blackouts: %s\n" % u.blackout_set.all()) else: outfile.write(" None\n") outfile.write("\n\nUsers with no PST ID:") users = list(User.objects.order_by("last_name")) values = [u for u in users if u.pst_id is None] print_values(outfile, values) outfile.write("\n\nPeriods Scheduled on blackout dates:") values = [] for s in sessions: for p in [p for p in s.period_set.all() if p.start >= datetime.today() \ and not p.isDeleted()]: blackouts = s.project.get_blackout_times(p.start, p.end()) if blackouts: values.append("%s on %s" % (s.name , p.start.strftime("%m/%d/%Y %H:%M"))) print_values(outfile, values) outfile.write("\n\nElective and Fixed pending periods scheduled on blackout dates:") values = [] opened = Session_Type.objects.get(type="open") windowed = Session_Type.objects.get(type="windowed") pending = Period_State.objects.get(name="Pending") for p in Period.objects \ .exclude(session__session_type=opened) \ .exclude(session__session_type=windowed) \ .filter(start__gte=now) \ .filter(state=pending).order_by("start"): blackouts = p.session.project.get_blackout_times(p.start, p.end()) if blackouts: values.append("%s" % p) print_values(outfile, values) outfile.write("\n\nOverlapping periods:") values = report_overlaps(periods, now = now) print_values(outfile, values) outfile.write("\n\nGaps in historical schedule:") ps = Period.objects.filter(start__lt = now)\ .filter(~Q(state__abbreviation = 'D')).order_by("start") values = [] previous = ps[0] for p in ps[1:]: # periods should be head to tail if p.start != previous.end() and p.start > previous.end(): values.append("Gap between: %s and %s" % (previous, p)) previous = p print_values(outfile, values) outfile.write("\n\nPeriods with time billed exceeding duration:") values = [p.__str__() for p in periods if p.duration < p.accounting.time_billed()] print_values(outfile, values) outfile.write("\n\nPeriods with non-positive durations:") values = [p for p in periods if p.duration <= 0.] print_values(outfile, values) outfile.write("\n\nPeriods with negative observed times:") values = [str(p) for p in periods if p.accounting.observed() < 0.] print_values(outfile, values) outfile.write("\n\nDeleted Periods with positive observed times:") ps = [p for p in periods if p.state.abbreviation == 'D'] values = [str(p) for p in ps if p.accounting.observed() > 0.] print_values(outfile, values) outfile.write("\n\nDeleted and Scheduled Periods for non-Windowed Sessions with non-positive scheduled time:") ps = [p for p in periods if p.state.abbreviation in ['D', 'S'] and p.session.session_type.type != 'windowed'] values = [p for p in ps if p.accounting.scheduled <= 0.0] print_values(outfile, values) outfile.write("\n\nPending Periods (non-windowed, non-elective):") values = [str(p) for p in periods if p.isPending() and not p.is_windowed() and not p.is_elective()] print_values(outfile, values) outfile.write("\n\nCompleted projects with non-complete sessions:") print_values(outfile, get_closed_projets_with_open_sessions()) outfile.write("\n\nSessions with wrong number of targets (!= 1):") values = sessions_with_null_or_multiple_targets() print_values(outfile, values) outfile.write("\n\nSessions with frequency == NULL:") print_values(outfile, Sesshun.objects.filter(frequency = None)) outfile.write("\n\nSessions with NULL RA and/or DEC:") values = sessions_with_bad_target() print_values(outfile, values) # * (new) Incomplete electives with insufficient opportunities: #* Electives: # o Elective sessions with no electives: # o Electives with no opportunities: # o Non-elective sessions with electives assigned: outfile.write("\n\nElective Sessions with no Electives:") values = elective_sessions_no_electives() print_values(outfile, values) outfile.write("\n\nNon-Elective Sessions with Electives:") values = non_elective_sessions_electives() print_values(outfile, values) outfile.write("\n\nElectives with no Opportunities (Periods):") values = electives_no_periods() print_values(outfile, values) outfile.write("\n\nPeriods from Elective Session not in an Elective:") ps = periods_no_elective() print_values(outfile, [str(p) for p in ps]) output_windows_report(outfile)
def get_obs_hours(sessions, typ): ta = TimeAccounting() return sum([ta.getTime("observed", s) for s in get_sessions(session, typ)])
class TestProposal(TestCase): fixtures = ['scheduler.json', 'proposal_GBT12A-002'] def setUp(self): super(TestProposal, self).setUp() # this project has no allotments! self.project = DSSProject.objects.order_by('pcode').all()[0] # setup some periods self.start = datetime(2000, 1, 1, 0) self.end = self.start + timedelta(hours = 12) times = [(datetime(2000, 1, 1, 0), 5.0, "one") , (datetime(2000, 1, 1, 5), 3.0, "two") , (datetime(2000, 1, 1, 8), 4.0, "three") ] self.ps = [] state = DSSPeriod_State.objects.get(abbreviation = 'P') for start, dur, name in times: # each session has grade 4, time = 3 s = create_sesshun() s.name = name s.save() pa = DSSPeriod_Accounting(scheduled = dur) pa.save() p = DSSPeriod( session = s , start = start , duration = dur , state = state , accounting = pa ) p.save() self.ps.append(p) # Okay, now set up the corresponding proposal now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") sqlResult = { 'PROP_ID' : self.project.pcode , 'PROPOSAL_TYPE' : 'Regular' , 'STATUS' : 'Draft' , 'SUBMITTED_DATE' : now , 'CREATED_DATE' : now , 'MODIFIED_DATE' : now , 'TITLE' : 'Lynrd Sknyrd' , 'ABSTRACT' : 'What song do you wanna hear?' , 'proposal_id' : 0 , 'JOINT_PROPOSAL_TYPE' : 'Not a joint Proposal' } proposal = Proposal.createFromSqlResult(sqlResult) proposal.dss_project = self.project proposal.setSemester(self.project.semester.semester) proposal.save() self.proposal = proposal self.ta = TimeAccounting() def tearDown(self): super(TestProposal, self).tearDown() for p in self.ps: s = p.session p.delete() s.delete() # TBF: stick this in a utility somewhere def createSession(self, p): "Create a new session for the tests" return createSession(p) def test_requestedTime(self): p = Proposal.objects.get(pcode = 'GBT09A-001') self.assertEqual(0.0, p.requestedTime()) # now get some requested time self.createSession(p) self.assertEqual(7.0, p.requestedTime()) def test_timeAccounting(self): self.assertEqual(12.0, self.ta.getTime('time_billed', self.project)) self.assertEqual(12.0, self.proposal.billedTime()) self.assertEqual(12.0, self.ta.getTime('scheduled', self.project)) self.assertEqual(12.0, self.proposal.scheduledTime()) self.assertEqual(-12.0, self.ta.getTimeRemaining(self.project)) self.assertEqual(-12.0, self.proposal.remainingTime()) def test_createFromSqlResult(self): sqlResult = {'SUPPORTED': u'\x00', 'FIRST_NAME': u'Carl', 'LAST_NAME': u'Gwinn', 'EMAIL': u'*****@*****.**', 'OLD_PI': u'None', 'TITLE': u'Substructure in the Scattering Disk of Sgr A*', 'RELATED_PROPOSALS': u'', 'ASSIGNMENT': u'None', 'ABSTRACT': u'We propose observations to detect, or set limits on, substructure within the smooth scattering disk of the celebrated galactic center radio source SgrA*. Such structure is predicted theoretically, and it may have been detected in observations of pulsars with RadioAstron, and in earlier observations of SgrA*. Results will place constraints on the spatial spectrum of the electron-density fluctuations that are responsible for the scattering.', 'CREATED_DATE': u'2013-01-26 18:18:54', 'contact_id': u'33166', 'JOINT_PROPOSAL_TYPE': u'Joint with GBT and VLA', 'OLD_CONTACT': u'None', 'DEADLINE_DATE': u'2013-02-01 22:30:00', 'PROCESSED': u'\x00', 'category2_id': u'None', 'STAFF_SUPPORT': u'Consultation', 'scienceCategory': u'Interstellar Medium', 'comments': u'', 'justificationFile_id': u'7403', 'MODIFIED_DATE': u'2013-02-04 21:57:56', 'user_id': u'2554', 'TELESCOPE': u'VLBA', 'OTHER_AWARDS': u'', 'reviewersConflict': u'\x00', 'allocated_hours': u'0.0', 'objectversion': u'0', 'principal_investigator_id': u'33166', 'RAPID_RESPONSE_TYPE': u'None', 'technicalCategory_id': u'78', 'category3_id': u'None', 'GRADUATION_YEAR': u'-1', 'person_id': u'2552', 'proposal_id': u'7917', 'disposition_letter': u'None', 'public': u'\x00', 'PRESENT': u'no', 'STATUS': u'SUBMITTED', 'trigger_criteria': u'None', 'dissertationPlan_id': u'None', 'PLAN_SUBMITTED': u'no', 'category1_id': u'None', 'SUPPORT_REQUESTER': u'\x00', 'DOMESTIC': u'\x01', 'PROFESSIONAL_STATUS': u'All Others', 'THESIS_OBSERVING': u'\x00', 'LOCK_MILLIS': u'0', 'STORAGE_ORDER': u'0', 'editor_id': u'33166', 'author_id': u'33166', 'SUBMITTED_DATE': u'2013-02-04 21:56:27', 'displayTechnicalReviews': u'\x00', 'DISPLAY_POSITION': u'0', 'LOCK_USER_ID': u'None', 'NEW_USER': u'\x00', 'PREV_PROP_IDS': u'None', 'PROPOSAL_TYPE': u'Regular', 'TELEPHONE': u'805-8932814', 'LOCK_USER_INFO': u'None', 'AFFILIATION': u'California at Santa Barbara, University of', 'BUDGET': u'0.0', 'OBSERVING_TYPE_OTHER': u'None', 'LEGACY_ID': u'BG221', 'ADDRESS': u'', 'PROP_ID': u'VLBA/13B-395', 'OLDAUTHOR_ID': u'2554', 'OLD_EDITOR': u'None'} p = Proposal.createFromSqlResult(sqlResult) pcode = 'VLBA13B-395' self.assertEqual(p.pcode, pcode) # now get fresh copy from db pdb = Proposal.objects.get(pcode = pcode) self.assertEqual(datetime(2013, 2, 4, 21, 56, 27), pdb.submit_date) self.assertEqual(datetime(2013, 2, 4, 21, 57, 56), pdb.modify_date) self.assertEqual(datetime(2013, 1, 26, 18, 18, 54), pdb.create_date) # now, recreate it, but w/ out the submit date pdb.delete() sqlResult['SUBMITTED_DATE'] = 'None' p = Proposal.createFromSqlResult(sqlResult) pcode = 'VLBA13B-395' self.assertEqual(p.pcode, pcode) # now get fresh copy from db pdb = Proposal.objects.get(pcode = pcode) self.assertEqual(datetime(2013, 2, 4, 21, 57, 56), pdb.modify_date) self.assertEqual(datetime(2013, 1, 26, 18, 18, 54), pdb.create_date) # the submit date should now be 'now' self.assertNotEqual(datetime(2013, 2, 4, 21, 56, 27), pdb.submit_date) frmt = '%Y-%m-%d %H:%M' now = datetime.now().strftime(frmt) self.assertEqual(now, pdb.submit_date.strftime(frmt)) # demonstrate that as long as it's unicode, we're cool pdb.delete() a = u'dog\xe0\xe1cat' sqlResult['ABSTRACT'] = a p = Proposal.createFromSqlResult(sqlResult) pdb = Proposal.objects.get(pcode = pcode) self.assertEqual(a, pdb.abstract)
class TestProposal(TestCase): fixtures = ['scheduler.json', 'proposal_GBT12A-002'] def setUp(self): super(TestProposal, self).setUp() # this project has no allotments! self.project = DSSProject.objects.order_by('pcode').all()[0] # setup some periods self.start = datetime(2000, 1, 1, 0) self.end = self.start + timedelta(hours = 12) times = [(datetime(2000, 1, 1, 0), 5.0, "one") , (datetime(2000, 1, 1, 5), 3.0, "two") , (datetime(2000, 1, 1, 8), 4.0, "three") ] self.ps = [] state = DSSPeriod_State.objects.get(abbreviation = 'P') for start, dur, name in times: # each session has grade 4, time = 3 s = create_sesshun() s.name = name s.save() pa = DSSPeriod_Accounting(scheduled = dur) pa.save() p = DSSPeriod( session = s , start = start , duration = dur , state = state , accounting = pa ) p.save() self.ps.append(p) # Okay, now set up the corresponding proposal now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") sqlResult = { 'PROP_ID' : self.project.pcode , 'PROPOSAL_TYPE' : 'Regular' , 'STATUS' : 'Draft' , 'SUBMITTED_DATE' : now , 'CREATED_DATE' : now , 'MODIFIED_DATE' : now , 'TITLE' : 'Lynrd Sknyrd' , 'ABSTRACT' : 'What song do you wanna hear?' , 'proposal_id' : 0 , 'JOINT_PROPOSAL_TYPE' : 'Not a joint Proposal' } proposal = Proposal.createFromSqlResult(sqlResult) proposal.dss_project = self.project proposal.setSemester(self.project.semester.semester) proposal.save() self.proposal = proposal self.ta = TimeAccounting() def tearDown(self): super(TestProposal, self).tearDown() for p in self.ps: s = p.session p.delete() s.delete() # TBF: stick this in a utility somewhere def createSession(self, p): "Create a new session for the tests" return createSession(p) def test_requestedTime(self): p = Proposal.objects.get(pcode = 'GBT09A-001') self.assertEqual(0.0, p.requestedTime()) # now get some requested time self.createSession(p) self.assertEqual(7.0, p.requestedTime()) def test_timeAccounting(self): self.assertEqual(12.0, self.ta.getTime('time_billed', self.project)) self.assertEqual(12.0, self.proposal.billedTime()) self.assertEqual(12.0, self.ta.getTime('scheduled', self.project)) self.assertEqual(12.0, self.proposal.scheduledTime()) self.assertEqual(-12.0, self.ta.getTimeRemaining(self.project)) self.assertEqual(-12.0, self.proposal.remainingTime())