Source code for viewclust_vis.job_stack

import plotly.graph_objects as go


[docs]def job_stack(jobs, use_unit='cpu', fig_out='', plot_title='', query_bounds=True): """Create job stack figure based on a given DataFrame and specified use unit. Each job is a rectangle, where the height of the rectangle is based on the amount of resources that are being examined. Further, all three job states are displayed: queued, running, end time. Parameters ------- jobs: DataFrame Job DataFrame typically generated by the ccmnt package. use_unit: str, optional Usage unit to examine. One of: {'cpu', 'cpu-eqv', 'gpu', 'gpu-eqv'}. Defaults to 'cpu'. fig_out: str, optional Writes the generated figure to file as specified. If empty, skips writing. Defaults to empty. plot_title: str, optional Title information passed to the figure object. query_bounds: bool, optional Draws red lines on the figure to represent where query is valid. Defaults to true. """ if use_unit == 'cpu': jobs['use_unit'] = jobs['reqcpus'] elif use_unit == 'cpu-eqv': jobs['mem_scale'] = jobs['mem'] / 4000.0 jobs['use_unit'] = jobs[['mem_scale', 'reqcpus']].max(axis=1) elif use_unit == 'gpu': jobs['ngpus'] = jobs['r_tres'].str.extract( r'(\d+)(?!.*\d)').astype('float') jobs['use_unit'] = jobs['ngpus'] else: print('gpu equiv to be supported soon') return cumu_sum_units = jobs['use_unit'].cumsum() res_count = 0 x_queue = [] x_run = [] x_req = [] # TODO: Fix this below section into frame calls y_cumu = [] for _, row in jobs.iterrows(): c_queue = [row['submit'], row['start'], row['start'], row['submit'], row['submit'], None] x_queue = x_queue + c_queue c_run = [row['start'], row['end'], row['end'], row['start'], row['start'], None] x_run = x_run + c_run c_req = [row['end'], row['start']+row['timelimit'], row['start']+row['timelimit'], row['end'], row['end'], None] x_req = x_req + c_req c_cumres = [res_count, res_count, res_count+row['use_unit'], res_count+row['use_unit'], res_count, None] y_cumu = y_cumu + c_cumres res_count = res_count+row['use_unit'] fig = go.Figure() fig.add_trace(go.Scatter( x=x_queue, y=y_cumu, fill='toself', fillcolor='rgba(200,200,200,.5)', line_color='rgba(200,200,200,.3)', name='queued', hoveron='points+fills', text=jobs['jobid'] )) fig.add_trace(go.Scatter( x=x_run, y=y_cumu, fill='toself', fillcolor='rgba(140,180,140,.9)', line_color='rgba(140,180,140,.1)', name='running' )) fig.add_trace(go.Scatter( x=x_req, y=y_cumu, fill='toself', fillcolor='rgba(120,120,180,.2)', line_color='rgba(120,120,180,.1)', name='requested' )) fig.add_trace(go.Scatter( x=jobs['submit'], y=cumu_sum_units-jobs['use_unit'], mode='markers', name='submit', marker_color='rgba(100,100,100,.3)', hovertext=jobs['jobid'] )) fig.add_trace(go.Scatter( x=jobs['start'], y=cumu_sum_units-jobs['use_unit'], mode='markers', name='start', marker_color='rgba(20,120,20,.3)', hovertext=jobs['jobid'] )) fig.add_trace(go.Scatter( x=jobs['end'], y=cumu_sum_units-jobs['use_unit'], mode='markers', name='end', marker_color='rgba(120,20,20,.3)', hovertext=jobs['jobid'] )) fig.add_trace(go.Scatter( x=jobs['start']+jobs['timelimit'], y=cumu_sum_units-jobs['use_unit'], mode='markers', name='end', marker_color='rgba(100,100,140,.3)', hovertext=jobs['jobid'] )) if query_bounds: Warning('Query bounds not yet implemented.') fig.update_layout( title_text="Job stack: "+plot_title, yaxis_title='Cumulative resources requested ('+str(use_unit)+')', xaxis_title='Date Time', showlegend=True) if fig_out != '': fig.write_html(fig_out) return fig