1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
|
libGDSII is a C++ library for working with GDSII binary data files, intended primarily for use with the computational electromagnetism codes
[scuff-em](http://homerreid.github.io/scuff-em-documentation)
and
[meep](http://meep.readthedocs.org)
but sufficiently general-purpose to allow other uses as well.
The packages consists of
+ a C++ library (`libGDSII`) with API functions for reading, processing, and exporting GDSII files
+ a command-line executable code (`GDSIIConvert`) for reporting statistics on GDSII geometries and
exporting them to other file formats, notably including the [GMSH](http://gmsh.info) geometry format.
# Installation
```bash
% git clone http://github.com/HomerReid/libGDSII
% cd libGDSII
% sh autogen.sh --prefix=/path/to/installation/prefix
% make install
```
This will install the `GDSIIConvert` executable in `$(prefix)/bin`
and the `libGDSII.a` and/or `libGDSII.so` library binaries in `$(prefix)/lib`.
# Using the `GDSIIConvert` command-line tool
The GDSII file referenced in the following examples is
[this silicon-photonics transceiver](https://github.com/lukasc-ubc/SiEPIC-Tools/blob/master/Examples/GSiP/RingModTransceiver/Layouts/GSiP_4_RingFilter.gds)
from the [SiEPIC-Tools](https://github.com/lukasc-ubc) project:
+ Lukas Chrostowski, Zeqin Lu, Jonas Flueckiger, Xu Wang, Jackson Klein,
Amy Liu, Jaspreet Jhoja, James Pond,
["Design and simulation of silicon photonic schematics and layouts,"](http://edx.org/course/silicon-photonics-design-fabrication-ubcx-phot1x)
Proc. SPIE 9891, Silicon Photonics and Photonic Integrated Circuits V, 989114 (May 13, 2016); doi:10.1117/12.2230376.
## Convert to [GMSH](http://gmsh.info) format: Option `--gmsh`
```bash
% GDSIIConvert --GMSH GSiP_4_RingFilter.gds
Read 2080 data records from file GSiP_4_RingFilter.gds.
Wrote 91 text strings to GSiP_4_RingFilter.pp.
Detecting metallization structures on layer 1: ... 34 polygons on layer 1
Detecting metallization structures on layer 3: ... 30 polygons on layer 3
Detecting metallization structures on layer 7: ... 2 polygons on layer 7
Detecting metallization structures on layer 10: ... 78 polygons on layer 10
Detecting metallization structures on layer 20: ... 1 polygons on layer 20
Detecting metallization structures on layer 21: ... 1 polygons on layer 21
Detecting metallization structures on layer 44: ... 12 polygons on layer 44
Detecting metallization structures on layer 47: ... 30 polygons on layer 47
Detecting metallization structures on layer 60: ... 2 polygons on layer 60
Detecting metallization structures on layer 63: ... 2 polygons on layer 63
Detecting metallization structures on layer 66: ... 87 polygons on layer 66
Detecting metallization structures on layer 68: ... 16 polygons on layer 68
Detecting metallization structures on layer 69: ... 46 polygons on layer 69
Detecting metallization structures on layer 81: ... 2 polygons on layer 81
Detecting metallization structures on layer 733: ... 2 polygons on layer 733
Wrote 345 metallization polygons to GSiP_4_RingFilter.geo.
Thank you for your support.
```
This produces two files: the GMSH geometry file `GSiP_4_RingFilter.geo,`
describing the polygons, and the GMSH post-processing file `GSiP_4_RingFilter.pp`
describing the text strings. These can be opened in GMSH for visualization:
```bash
% gmsh GSiP_4_RingFilter.geo GSiP_4_RingFilter.pp
```
![GMSH screenshot](GMSHScreenshot.png)
### Extracting individual layers
If you only want to extract polygons on a single layer, you can
add e.g. `--MetalLayer 47` to the `GDSIIConvert` command line:
```bash
% GDSIIConvert --GMSH --MetalLayer 47 GSiP_4_RingFilter.geo --FileBase GSIP_47
% GDSIIConvert --GMSH --MetalLayer 69 GSiP_4_RingFilter.geo --FileBase GSIP_69
```
## Print text description of geometry hierarchy: Option `--analyze`
```bash
% GDSIIConvert --analyze GSiP_4_RingFilter.gds
Read 2080 data records from file GSiP_4_RingFilter.gds.
*
* File GSiP_4_RingFilter.gds:
* Unit=1.000000e-06 meters (file units = {1.000000e-03,1.000000e-09})
*
**************************************************
** Library SiEPIC_GSiP:
**************************************************
--------------------------------------------------
** Struct 0: $$$CONTEXT_INFO$$$
--------------------------------------------------
Element 0: SREF (layer 0, datatype 0)
(structure CIRCLE)
(attribute 7: PCELL_CIRCLE)
(attribute 6: P_actual_radius)
(attribute 5: P_npoints)
(attribute 4: P_handle___dpoint)
(attribute 3: P_radius)
(attribute 2: P_layer___layer)
(attribute 1: LIB_Basic)
(attribute 0: LIB_SiEPIC_GSiP)
XY: 0 0
Element 1: SREF (layer 0, datatype 0)
(structure OpticalFibre__micron)
(attribute 1: CELL_OpticalFibre__micron)
(attribute 0: LIB_SiEPIC_GSiP)
XY: 0 0
Element 2: SREF (layer 0, datatype 0)
(structure ROUND_PATH$)
...
...
...
Element 18: SREF (layer 0, datatype 0)
(structure ROUND_PATH$)
XY: 0 0
Element 19: SREF (layer 0, datatype 0)
(structure ROUND_PATH$)
XY: 0 0
Element 20: BOUNDARY (layer 20, datatype 0)
XY: 228898 187725 228803 187791 228898 187931 228898 187725
Element 21: BOUNDARY (layer 21, datatype 0)
XY: 234248 192138 234248 192595 234250 192366 234248 192138
Thank you for your support.
```
## Print low-level description of GDSII file structure (data records): Option `--raw`
```bash
% GDSIIConvert --raw GSiP_4_RingFilter.gds
Record 0: HEADER ( 1) = 600
Record 1: BGNLIB ( 12) = 2017 3 16 23 29 47 2017 3 16 23 29 47
Record 2: LIBNAME ( 1) = SiEPIC_GSiP
Record 3: UNITS ( 2) = 0.001 1e-09
Record 4: BGNSTR ( 12) = 2017 3 16 23 29 47 2017 3 16 23 29 47
Record 5: STRNAME ( 1) = $$$CONTEXT_INFO$$$
Record 6: SREF =
Record 7: SNAME ( 1) = CIRCLE
Record 8: XY ( 2) = 0 0
Record 9: PROPATTR ( 1) = 7
Record 10: PROPVALUE ( 1) = PCELL_CIRCLE
Record 11: PROPATTR ( 1) = 6
Record 12: PROPVALUE ( 1) = P_actual_radius
...
...
...
Record 2066: XY ( 2) = 0 0
Record 2067: ENDEL =
Record 2068: BOUNDARY =
Record 2069: LAYER ( 1) = 20
Record 2070: DATATYPE ( 1) = 0
Record 2071: XY ( 8) = 228898 187725 228803 187791 228898 187931 228898 187725
Record 2072: ENDEL =
Record 2073: BOUNDARY =
Record 2074: LAYER ( 1) = 21
Record 2075: DATATYPE ( 1) = 0
Record 2076: XY ( 8) = 234248 192138 234248 192595 234250 192366 234248 192138
Record 2077: ENDEL =
Record 2078: ENDSTR =
Record 2079: ENDLIB =
Read 2080 data records from file SiEPIC/GSiP_4_RingFilter.gds.
Thank you for your support.
```
# Using the `libGDSII` API
## Overview of the `libGDSII` API
`libGDSII` exports a C++ class called `GDSIIData,` whose
class constructor accepts the name of a binary GDSII file as input.
Internally, the constructor maintains both a *hierarchical* representation
of the geometry (involving structures that instantiate other structures,
arrays of structure elements, etc.) and a *flat* representation,
consisting simply of collections of polygons and text labels,
indexed by the layer on which they appeared.
The flat representation consists of
+ an integer-valued array `Layers`, with `Layers[0], Layers[1], ...` the indices of the layers present in the GDSII file
+ for each layer, an array of `Entity` structures, where each `Entity` is either a polygon or a text string:
```C++
std::vector<int> Layers; // Layers[nl] = index of layer #nl in GDSII file
typedef struct Entity
{ char *Text; // if NULL, the entity is a polygon; otherwise it is a text string
dVec XY; // vertex coordinates: 2 for a text string, 2N for an N-gon
bool Closed; // true if there exists an edge connecting the last to the first vertex
char *Label; // optional descriptive text, may be present or absent for polygons and texts
} Entity;
typedef std::vector<Entity> EntityList;
typedef std::vector<EntityList> EntityTable; // EntityTable[nl][ne] = entity #ne on layer Layers[nl]
```
In the flat representation, all GDSII geometry elements---including
boundaries, boxes, paths, structure instantiations (`SREF`s), and
arrays (`AREF`s)---are reduced to polygons, described by lists
of *N>1* vertices, with each vertex having two coordinates (*x* and *y*).
The *2N* vertex coordinates are stored internally in the `XY` field
of `Entity`, a `double`-valued `std::vector.` The `Closed` flag
indicates whether or not the polygon includes an edge connecting
vertex *N* back to vertex *1*.
If the `Text` field of `Entity` is non-NULL, the entity is not a polygon,
but is instead a text string. In this case the `XY` array has length 2,
the (*x,y*) coordinates of the text reference point.
Both polygons and text strings may be accompanied by
optional descriptive text, stored in the `*Label` field of `Entity.`
`GDSIIData` provides API routines for extracting polygons from GDSII geometries.
This can be done in a couple of ways:
+ You can ask for a list of all polygons on a given layer. If there is more than one polygon on the layer, you will get them all, in the form of an unsorted array.
+ You can specify a label (character string) and ask for only those polygons that contain the reference point of a text string, on the same layer, matching your string. You can restrict this search to a single layer, or search all layers in the file; in the latter case, only polygons that live on the same layer as the text string are returned.
Arrays of polygons are returned in the form of a `vector` of `double`-valued `vectors`:
```C++
typedef vector<double> dVec;
typedef vector<dVec> PolygonList; // PolygonList[np][2*nv+0,2*nv+1] = x,y coords of vertex #nv in polygon #np
```
## Sample code
```C++
#include "libGDSII.h"
using namespace std;
using namespace libGDSII;
/********************************************************************/
/* try to instantiate GDSIIData structure from binary GDSII file */
/********************************************************************/
GDSIIData *gdsIIData = new GDSIIData( string("GSiP_4_RingFilter.gds") );
if (gdsIIData->ErrMsg)
{ printf("error: %s (aborting)\n",gdsIIData->ErrMsg->c_str());
exit(1);
}
/***************************************************************/
/* output a text-based description of the geometry */
/***************************************************************/
gdsIIData->WriteDescription(); // writes to console
gdsIIData->WriteDescription("MyOutputFile");
/***************************************************************/
/* get all polygons on layer 3 *********************************/
/***************************************************************/
PolygonList Layer3Polygons = gdsIIData->GetPolygons(3);
printf("Found %lu polygons on layer 3: \n",Layer3Polygons.size());
for(size_t np=0; np<Layer3Polygons.size(); np++)
{ printf("Polygon #%lu has vertices: ",np);
for(int nv=0; nv<Layer3Polygons[np].size()/2; nv++)
printf(" {%e,%e} ",Layer3Polygons[np][2*nv+0],Layer3Polygons[2*nv+1]);
printf("\n");
}
/***************************************************************/
/* get all polygons on layer 3 that contain the reference point*/
/* of the text string "Geometry" (also on layer 3) */
/***************************************************************/
PolygonList Layer3Polygons = gdsIIData->GetPolygons("Geometry", 3);
/***************************************************************/
/* get all polygons on any layer that contain the reference pt */
/* of the text string "Geometry" on the same layer */
/***************************************************************/
PolygonList Layer3Polygons = gdsIIData->GetPolygons("Geometry");
```
## Internal caching of `GDSIIData` structure
In the above snippet, we create an instance of `class GSDIIData`
and access the geometry by calling the class methods of this
instance. `libGDSII` also provides an alternative interface
in which you call non-class methods, passing only the GDSII file name:
```C++
PolygonList Layer3Polygons = GetPolygons("MyGDSFile.GDS", 3);
PolygonList Layer3Geometry = GetPolygons("MyGDSFile.GDS", "Geometry", 3);
...
...
void ClearGDSIICache();
```
In this case what is going on is that `libGDSII` is creating and internally
storing a `GDSIIData` structure for the given GDS file. Successive
calls to `GetPolygons` with the same file name will re-use the cached data
structure, saving the cost of rereading the GDS file. If you make
subsequent calls to `GetPolygons` with a new GDS file, the cached data will
be destroyed and allocated anew for the new file.
When finished with a sequence of `GetPolygons()` calls of this form,
call `ClearGDSIICache()` to deallocate memory associated with the
internally-cached structures.
|