#438 add thread and ternary plots

Open Lori A. Burns loriab
Coverage Reach
interface/collections/dataset.py interface/collections/reaction_dataset.py interface/collections/dataset_view.py interface/collections/collection.py interface/collections/torsiondrive_dataset.py interface/collections/optimization_dataset.py interface/collections/gridoptimization_dataset.py interface/collections/collection_utils.py interface/collections/generic.py interface/collections/__init__.py interface/models/rest_models.py interface/models/records.py interface/models/torsiondrive.py interface/models/gridoptimization.py interface/models/common_models.py interface/models/task_models.py interface/models/model_utils.py interface/models/model_builder.py interface/models/__init__.py interface/client.py interface/visualization.py interface/statistics.py interface/data/data_getters.py interface/data/__init__.py interface/util.py interface/__init__.py interface/hash_helpers.py storage_sockets/sqlalchemy_socket.py storage_sockets/models/results_models.py storage_sockets/models/sql_models.py storage_sockets/models/collections_models.py storage_sockets/models/sql_base.py storage_sockets/models/__init__.py storage_sockets/db_queries.py storage_sockets/api_logger.py storage_sockets/storage_socket.py storage_sockets/storage_utils.py storage_sockets/__init__.py queue/managers.py queue/handlers.py queue/parsl_adapter.py queue/base_adapter.py queue/executor_adapter.py queue/fireworks_adapter.py queue/adapters.py queue/__init__.py cli/qcfractal_manager.py cli/qcfractal_server.py cli/cli_utils.py cli/qcfractal_dashboard.py services/service_util.py services/gridoptimization_service.py services/torsiondrive_service.py services/services.py services/__init__.py testing.py server.py procedures/procedures.py procedures/procedures_util.py procedures/__init__.py snowflake.py postgres_harness.py web_handlers.py config.py extras.py util.py __init__.py

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.

Showing 1 of 1 files from the diff.

@@ -229,3 +229,280 @@
Loading
229 229
    figure = go.Figure(data=data, layout=layout)
230 230
231 231
    return _configure_return(figure, "qcportal-violin", return_figure)
232 +
233 +
234 +
def threads(data, labels, color=None, title='', xlimit=4.0, mae=None, mape=None,
235 +
    mousetext=None, mouselink=None, mouseimag=None, mousetitle=None, mousediv=None,
236 +
    labeled=True, view=True,
237 +
    saveas=None, relpath=False, graphicsformat=['pdf']):
238 +
    """Generates a tiered slat diagram between model chemistries with
239 +
    errors (or simply values) in list *data*, which is supplied as part of the
240 +
    dictionary for each participating reaction, along with *dbse* and *rxn* keys
241 +
    in argument *data*. The plot is labeled with *title* and each tier with
242 +
    an element of *labels* and plotted at *xlimit* from the zero-line. If
243 +
    *color* is None, slats are black, if 'sapt', colors are taken from *color*
244 +
    key in *data* [0, 1]. Summary statistics *mae* are plotted on the
245 +
    overbound side and relative statistics *mape* on the underbound side.
246 +
    HTML code for mouseover if mousetext or mouselink or mouseimag specified
247 +
    based on recipe of Andrew Dalke from
248 +
    http://www.dalkescientific.com/writings/diary/archive/2005/04/24/interactive_html.html
249 +
250 +
    """
251 +
    import hashlib
252 +
253 +
    # initialize tiers/wefts
254 +
    Nweft = len(labels)
255 +
    lenS = 0.2
256 +
    gapT = 0.04
257 +
    positions = range(-1, -1 * Nweft - 1, -1)
258 +
    posnS = []
259 +
    for weft in range(Nweft):
260 +
        posnS.extend([positions[weft] + lenS, positions[weft] - lenS, None])
261 +
    posnT = []
262 +
    for weft in range(Nweft - 1):
263 +
        posnT.extend([positions[weft] - lenS - gapT, positions[weft + 1] + lenS + gapT, None])
264 +
    posnM = []
265 +
    xticks = [-0.5 * xlimit, -0.25 * xlimit, 0.0, 0.25 * xlimit, 0.5 * xlimit]
266 +
267 +
    # initialize plot
268 +
    import plotly.graph_objects as go
269 +
    fig = go.Figure()
270 +
271 +
    fig.update_layout(
272 +
        autosize=False,
273 +
        width=72 * 11,
274 +
        height=72 * Nweft * 0.8,
275 +
        margin=dict(b=36, l=7, r=7, t=34, pad=0),
276 +
        showlegend=False,
277 +
        xaxis=dict(range=[-xlimit, xlimit], tickvals=xticks, zeroline=True, zerolinewidth=3),
278 +
        yaxis=dict(range=[-1 * Nweft - 1, 0], showticklabels=False),
279 +
    )
280 +
    
281 +
    # label plot and tiers
282 +
    annot = []
283 +
    annot.append(go.layout.Annotation(
284 +
        x=-0.9 * xlimit,
285 +
        y=-0.25,
286 +
        align='left',
287 +
        #xanchor='left',
288 +
        text=title,
289 +
        showarrow=False,
290 +
        font=dict(size=12),
291 +
    ))
292 +
    for weft in labels:
293 +
        annot.append(go.layout.Annotation(
294 +
            x=-0.9 * xlimit,
295 +
            y=-(1.0 + labels.index(weft)),
296 +
            xref="x",
297 +
            yref="y",
298 +
            text=weft,
299 +
            align='left',
300 +
            showarrow=False,
301 +
            font=dict(size=18),
302 +
        ))
303 +
    fig.update_layout(annotations=annot)
304 +
305 +
#     if labeled:
306 +
#         ax.text(-0.9 * xlimit, -0.25, title,
307 +
#             verticalalignment='bottom', horizontalalignment='left',
308 +
#             family='Times New Roman', weight='bold', fontsize=12)
309 +
#         for weft in labels:
310 +
#             ax.text(-0.9 * xlimit, -(1.2 + labels.index(weft)), weft,
311 +
#                 verticalalignment='bottom', horizontalalignment='left',
312 +
#                 family='Times New Roman', weight='bold', fontsize=18)
313 +
314 +
    # plot reaction errors and threads
315 +
    for rxn in data:
316 +
317 +
        # preparation
318 +
        xvals = rxn['data']
319 +
        clr = rxn['color'] if 'color' in rxn else 'green' 
320 +
        slat = []
321 +
        for weft in range(Nweft):
322 +
            slat.extend([xvals[weft], xvals[weft], None])
323 +
        thread = []
324 +
        for weft in range(Nweft - 1):
325 +
            thread.extend([xvals[weft], xvals[weft + 1], None])
326 +
327 +
        # plotting
328 +
        fig.add_trace(go.Scatter(x=slat,
329 +
                                 y=posnS,
330 +
                                 mode='lines',
331 +
                                 name=rxn['sys'],
332 +
                                 line=dict(
333 +
                                     color=clr,
334 +
                                     dash='solid',
335 +
                                     width=1.0,
336 +
                                 ),
337 +
                                ))
338 +
339 +
        fig.add_trace(go.Scatter(x=thread, y=posnT,
340 +
                                 mode='lines',
341 +
                                 name=rxn['sys'],
342 +
                                 opacity=0.6, #0.3,
343 +
                                 showlegend=False,
344 +
                                 line=dict(
345 +
                                     color=clr,
346 +
                                     dash='solid',
347 +
                                     width=0.5,
348 +
                                 ),                        
349 +
                                ))
350 +
        
351 +
    # plot trimmings
352 +
    if mae is not None:
353 +
        fig.add_trace(go.Scatter(x=[-x for x in mae], y=list(positions),
354 +
                                 mode='markers',
355 +
                                 name='MAE',
356 +
                                 marker=dict(
357 +
                                     color='black',
358 +
                                     symbol='square'),
359 +
                                ))
360 +
    if mape is not None:  # equivalent to MAE for a 10 kcal/mol IE
361 +
        fig.add_trace(go.Scatter(x=[0.025 * x for x in mape], y=list(positions),
362 +
                                 mode='markers',
363 +
                                 name='MA%E',
364 +
                                 marker=dict(
365 +
                                     color='black',
366 +
                                     symbol='circle'),
367 +
                                ))
368 +
369 +
    # save and show
370 +
    pltuid = title + '_' + ('lbld' if labeled else 'bare') + '_' + hashlib.sha1((title + repr(labels) + repr(xlimit)).encode()).hexdigest()
371 +
372 +
    if view:
373 +
        fig.show()
374 +
    return fig
375 +
376 +
377 +
def ternary(sapt, title='', labeled=True, view=True,
378 +
            saveas=None, relpath=False, graphicsformat=['pdf']):
379 +
    """Takes array of arrays *sapt* in form [elst, indc, disp] of [elst, indc, disp, lbl] and builds formatted
380 +
    two-triangle ternary diagrams. Either fully-readable or dotsonly depending
381 +
    on *labeled*. Saves in formats *graphicsformat*.
382 +
    """
383 +
    import hashlib
384 +
    import plotly.graph_objects as go
385 +
    fig = go.Figure()
386 +
387 +
    # initialize plot
388 +
    fig.update_layout(
389 +
        #autosize=False,
390 +
        height=400,
391 +
        #width=72 * 6,
392 +
        #height=72 * 3.6,
393 +
        showlegend=False,
394 +
        xaxis=dict(range=[-0.75, 1.25], showticklabels=False, zeroline=False),
395 +
        yaxis=dict(range=[-0.18, 1.02], showticklabels=False, zeroline=False,
396 +
                   scaleanchor="x", scaleratio=1),
397 +
    )
398 +
 
399 +
    if labeled:
400 +
    
401 +
        # form and color ternary triangles
402 +
        fig.update_layout(
403 +
            shapes=[
404 +
                go.layout.Shape(
405 +
                    type="path",
406 +
                    path="M0, 0 L1, 0 L0.5, 0.866, Z",
407 +
                    line_color="black",
408 +
                    fillcolor="white",
409 +
                    layer="below",
410 +
                ),
411 +
                go.layout.Shape(
412 +
                    type="path",
413 +
                    path="M0, 0 L-0.5, 0.866 L0.5, 0.866, Z",
414 +
                    line_color="black",
415 +
                    fillcolor="#fff5ee",
416 +
                    layer="below",
417 +
                ),
418 +
            ])
419 +
420 +
#         # form and color HB/MX/DD dividing lines
421 +
#         ax.plot([0.667, 0.5], [0., 0.866], color='#eeb4b4', lw=0.5)
422 +
#         ax.plot([-0.333, 0.5], [0.577, 0.866], color='#eeb4b4', lw=0.5)
423 +
#         ax.plot([0.333, 0.5], [0., 0.866], color='#7ec0ee', lw=0.5)
424 +
#         ax.plot([-0.167, 0.5], [0.289, 0.866], color='#7ec0ee', lw=0.5)
425 +
426 +
        # label corners
427 +
        fig.update_layout(annotations=[
428 +
            go.layout.Annotation(
429 +
                x=1.0,
430 +
                y=-0.08,
431 +
                text=u'<b>Elst (\u2212)</b>',
432 +
                showarrow=False,
433 +
                font=dict(family="Times New Roman", size=18),
434 +
            ),
435 +
            go.layout.Annotation(
436 +
                x=0.5,
437 +
                y=0.94,
438 +
                text=u'<b>Ind (\u2212)</b>',
439 +
                showarrow=False,
440 +
                font=dict(family="Times New Roman", size=18),
441 +
            ),
442 +
            go.layout.Annotation(
443 +
                x=0.0,
444 +
                y=-0.08,
445 +
                text=u'<b>Disp (\u2212)</b>',
446 +
                showarrow=False,
447 +
                font=dict(family="Times New Roman", size=18),
448 +
            ),
449 +
            go.layout.Annotation(
450 +
                x=-0.5,
451 +
                y=0.94,
452 +
                text=u'<b>Elst (+)</b>',
453 +
                showarrow=False,
454 +
                font=dict(family="Times New Roman", size=18),
455 +
            ),
456 +
        ])
457 +
458 +
    xvals = []
459 +
    yvals = []
460 +
    cvals = []
461 +
    lvals = []
462 +
    for sys in sapt:
463 +
        if len(sys) == 3:
464 +
            [elst, indc, disp] = sys
465 +
            lbl = ''
466 +
        elif len(sys) == 4:
467 +
            [elst, indc, disp, lbl] = sys
468 +
469 +
        # calc ternary posn and color
470 +
        Ftop = abs(indc) / (abs(elst) + abs(indc) + abs(disp))
471 +
        Fright = abs(elst) / (abs(elst) + abs(indc) + abs(disp))
472 +
        xdot = 0.5 * Ftop + Fright
473 +
        ydot = 0.866 * Ftop
474 +
        cdot = 0.5 + (xdot - 0.5) / (1. - Ftop)
475 +
        if elst > 0.:
476 +
            xdot = 0.5 * (Ftop - Fright)
477 +
            ydot = 0.866 * (Ftop + Fright)
478 +
479 +
        xvals.append(xdot)
480 +
        yvals.append(ydot)
481 +
        cvals.append(cdot)
482 +
        lvals.append(lbl)
483 +
484 +
    fig.add_trace(go.Scatter(x=xvals, y=yvals,
485 +
                             text=lvals,
486 +
                             mode='markers',
487 +
                             marker=dict(
488 +
                                 color=cvals,
489 +
                                 colorscale='Jet',
490 +
                                 size=6,
491 +
                             ),                        
492 +
                  ))
493 +
494 +
#     sc = ax.scatter(xvals, yvals, c=cvals, s=15, marker="o", \
495 +
#         cmap=mpl.cm.jet, edgecolor='none', vmin=0, vmax=1, zorder=10)
496 +
497 +
#     # remove figure outline
498 +
#     ax.spines['top'].set_visible(False)
499 +
#     ax.spines['right'].set_visible(False)
500 +
#     ax.spines['bottom'].set_visible(False)
501 +
#     ax.spines['left'].set_visible(False)
502 +
503 +
    # save and show
504 +
    pltuid = title + '_' + ('lbld' if labeled else 'bare') + '_' + hashlib.sha1((title + repr(sapt)).encode()).hexdigest()
505 +
506 +
    if view:
507 +
        fig.show()
508 +
    return fig

Learn more Showing 1 files with coverage changes found.

Changes in qcfractal/queue/parsl_adapter.py
-1
+1
Loading file...
Files Coverage
qcfractal -0.82% 86.97%
Project Totals (67 files) 86.97%
Loading