Home Forums Nazca how to get the matplolib figure?

Tagged: ,

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #6145
    bastien
    Member

    Hi,

    I’d like to get the matplotlib figure corresponding to a layout so that I can make a plot showing my overall layout design and close-ups of some critical features in various subplots. Is there a way to do that?

    Also, is there a way to use a different plotting library? I’d love to be able to use plotly in a jupyter notebook.

    Thanks,

    Bastien

     

    #6147
    Ronald
    Keymaster

    Dear Bastien,

    For matplotlib export use nd.export_plt() or alias nd.export_png().
    Notice that after export the design will be cleared. So in the next example the second export would be empty:

    nd.export_gds() 
    nd.export_plt()  # will be empty

    To keep the design alive you can use clear=False in the call:

    nd.export_gds(clear=False) 
    nd.export_plt()  # export to png as expected

    This behaviour is specifically introduced for working in Jupyter notebooks. So when you rerun a cell you do not stack design upon design by default, but if you run stuff in a sequence of cells you can set the clear=False.

    Matplotlib is flexible but notoriously on the slow side. If you put a lot of frames in you color definition things will slow down.

    For svg export you need to have svgwrite installed and simply use nd.export_svg(). With svg you can still edit some details for a presentation for example.

    More layout export types can be added relatively easy. Each type resides in separate class that receives the same layout info from the Nazca layout engine, such as polygons, lines and annotations, but exports it to the specific format.

    Ronald

    #6153
    bastien
    Member

    Hi Ronald,

    Thanks for your answer. I am aware of export_plt() and of the clear=False option and this isn’t exactly what I was looking for.  Thanks for pointing at the class, I looked a bit into it and saw that you just need the coordinates of the vertices making up a cell and with help of that post I came up with something that works pretty well for what I had in mind (adding annotation to document a library of layouts or having two subplots side by side). Here is a code snippet demonstrating it in case someone’s interested:

    import plotly.graph_objects as go
    
    nd.clear_layout()
    a = nd.strt(width=5, layer = 1).put()
    b = nd.bend( width=5, layer = 1).put()
    coord = []
    
    for NT in nd.cell_iter(nd.cfg.defaultcell, flat=True):
        if NT.cell_start:
            print(f"\ncell: '{NT.cell.cell_name}'")
            for i, (pgon, points, bbox) in enumerate(NT.iters['polygon']):
               #print(f"{i}: points: {points}, layer: '{pgon.layer}'")
               coord.append(points)
    
    x0 = [i[0] for i in coord[0]]
    x0.append(x0[0]) #to connect last point to first point in the plot
    y0 = [i[1] for i in coord[0]]
    y0.append(y0[0]) #to connect last point to first point in the plot
    x1 = [i[0] for i in coord[1]]
    x1.append(x1[0])
    y1 = [i[1] for i in coord[1]]
    y1.append(y1[0])
    
    fig = go.Figure([
        go.Scatter(x=x0, y=y0, fill="toself", marker=dict(opacity=0), name="arc layer1"),
        go.Scatter(x=x1, y=y1, fill="toself", marker=dict(opacity=0) )
    ])
    
    fig.add_annotation(
        x=5,
        y=2.5,
        text="L",
        ax=0,
        ay=-40
    )
    
    fig.add_annotation(
        x=0,
        y=0,
        text="W",
        ax=-20,
        ay=-40
    )
    
    fig.update_annotations(dict(
        xref="x",
        yref="y",
        showarrow=True,
        arrowhead=7
    ))
    
    fig.update_layout(
        yaxis = dict(
            scaleanchor = "x",
            scaleratio = 1,
        ),
        showlegend = True,
        width=1000, 
        height=1000,
        autosize=False
    )
    
    fig.show()
    nd.clear_layout()

    Bastien

    • This reply was modified 2 months, 1 week ago by bastien.
    • This reply was modified 2 months, 1 week ago by bastien.
    • This reply was modified 2 months ago by Ronald. Reason: formatting
    #6159
    Ronald
    Keymaster

    Dear Bastien,

    The cell iterator would indeed be a good way to get access all the layout info.

    I am not familiar with plotly, but I noticed it has to run in a browser to show the plot (JavaScript output) and it needs an offline mode if not run through a plotly account. I adjusted the code a bit to make it run for me in a notebook (see code below).

    More generic in Nazca, the layout to the various formats (gds, svg, png) receives input from the iterator in layout.py. Full Nazca-plotly integration would need a small class with methods for fig open, plot shapes for polygons, polylines and annotations, and a figure close/show, similar to e.g. class ClsMatplotlib.

    import nazca as nd
    from plotly.offline import plot
    import plotly.graph_objects as go
    nd.clear_layout()
    
    a = nd.strt(width=5, layer=1).put()
    b = nd.bend( width=5, layer=1).put()
    
    X, Y, lay = [], [], []
    for NT in nd.cell_iter(nd.cfg.defaultcell, flat=True):
        if NT.cell_start:
            print(f"cell: '{NT.cell.cell_name}'")
            for k, (pgon, points, bbox) in enumerate(NT.iters['polygon']):
                X.append([xy[0] for xy in points])
                Y.append([xy[1] for xy in points])
                lay.append(nd.get_layer_tuple(pgon.layer)[0]) # tuple: (layer, datatype, technology)
      
    fig = go.Figure()
    
    for x, y, l in zip(X, Y, lay):
        fig.add_trace(
            go.Scatter(x=x, y=y, fill="toself", marker=dict(opacity=0), fillcolor='red'),
        )
    
    fig.add_annotation(
        x=5,
        y=2.5,
        text="L",
        ax=0,
        ay=-40
    )
    
    fig.add_annotation(
        x=0,
        y=0,
        text="W",
        ax=-20,
        ay=-40
    )
    
    fig.update_annotations(dict(
        xref="x",
        yref="y",
        showarrow=True,
        arrowhead=7
    ))
    
    fig.update_layout(
        yaxis = dict(
            scaleanchor = "x",
            scaleratio = 1,
        ),
        showlegend = True,
        width=1000, 
        height=1000,
        autosize=False
    )
    
    plot(fig)

    Ronald

    #6161
    bastien
    Member

    Dear Ronald,

    Plotly is indeed more oriented for use in a web browser and it’s my visualization tool of choice in Jupyter lab. You might need to install an extension to get it to work in Jupyter though. You do not need an account to do all the basic plotting, as far as I understand you need an account only if you want to save plots on their servers (I remember this really confused me as well when I started using it a couple years ago but that has been somewhat clarified since version 4).

    It should be fairly easy to implement a class with the methods you mentioned and I could contribute code when I’ve some time. Is there a good place for that?

    Bastien

    #6162
    Ronald
    Keymaster

    Hi Bastien,

    It seems plotly gets installed via Anaconda as well. Anyway, I already implemented a plotly export class as it was quite easy to do and it allows for some faster panning and zooming than matplotllib, probably. Hence, in Nazca.0.5.12 you can try nd.export_plotly() in a Jupyter Notebook. I implemented the basics for polygons and the color schema.

    Ronald

    #6163
    bastien
    Member

    Great!

    Would it be possible to have a kwarg to return the figure in nd.export_plotly() so that it can be updated later on? For instance:

    
    fig = nd.export_plotly(return_figure = True)
    
    fig.add_annotation(...)
    

    return_figure = False could be set as default to keep it consistent with other export functions.

    Bastien

Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.