cnotebook 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cnotebook/render.py ADDED
@@ -0,0 +1,198 @@
1
+ import logging
2
+ import base64
3
+ from .context import CNotebookContext, pass_cnotebook_context
4
+ from openeye import oechem, oedepict
5
+
6
+ log = logging.getLogger("cnotebook")
7
+
8
+
9
+ ########################################################################################################################
10
+ # Renderers for specific types
11
+ ########################################################################################################################
12
+
13
+ def create_img_tag(
14
+ width: float,
15
+ height: float,
16
+ image_mime_type: str,
17
+ image_bytes: bytes,
18
+ wrap_svg: bool = True
19
+
20
+ ) -> str:
21
+ """
22
+ Create the <img> HTML tag for rendering image bytes. This could be either plain text (in the case of SVG) or base64
23
+ encoded (in binary format cases).
24
+ :param width: Image width
25
+ :param height: Image height
26
+ :param image_mime_type: Image MIME type
27
+ :param image_bytes: Image bytes
28
+ :param wrap_svg: Wrap SVG in a specifically sized <div> tag for maximum control of size
29
+ :return: Image tag
30
+ """
31
+ if image_mime_type == "image/svg+xml":
32
+ if wrap_svg:
33
+ return '<div style=\'width:{}px;max-width:{}px;height:{}px;max-height:{}px\'>\n\t{}\n</div>'.format(
34
+ int(width),
35
+ int(width),
36
+ int(height),
37
+ int(height),
38
+ image_bytes.decode("utf-8")
39
+ )
40
+ else:
41
+ return image_bytes.decode("utf-8")
42
+
43
+ return '<img src=\'data:{};base64,{}\' style=\'width:{}px;max-width:{}px;height:{}px;max-height:{}px\' />'.format(
44
+ image_mime_type,
45
+ base64.b64encode(image_bytes).decode("utf-8"),
46
+ int(width),
47
+ int(width),
48
+ int(height),
49
+ int(height)
50
+ )
51
+
52
+
53
+ @pass_cnotebook_context
54
+ def oedisp_to_html(
55
+ disp: oedepict.OE2DMolDisplay,
56
+ *,
57
+ ctx: CNotebookContext
58
+ ) -> str:
59
+ """
60
+ Convert an OpenEye 2D molecule display object to HTML
61
+ :param ctx: Current molecule render context
62
+ :param disp: OpenEye 2D molecule display object
63
+ :return: HTML image tag
64
+ """
65
+ # Convert the display object to an <img> tag
66
+ image = oedepict.OEImage(disp.GetWidth(), disp.GetHeight())
67
+ oedepict.OERenderMolecule(image, disp)
68
+ image_bytes = oedepict.OEWriteImageToString(ctx.image_format, image)
69
+
70
+ return create_img_tag(
71
+ disp.GetWidth(),
72
+ disp.GetHeight(),
73
+ image_mime_type=ctx.image_mime_type,
74
+ image_bytes=image_bytes,
75
+ wrap_svg=ctx.structure_scale != oedepict.OEScale_AutoScale
76
+ )
77
+
78
+
79
+ def render_empty_molecule(*, ctx: CNotebookContext) -> str:
80
+ """
81
+ Render an image that says Empty Molecule
82
+ :param ctx: Render context
83
+ :return: Image tag
84
+ """
85
+ image = oedepict.OEImage(ctx.min_width, ctx.min_height)
86
+ image.DrawText(
87
+ oedepict.OE2DPoint(ctx.min_width / 2, ctx.min_height / 2),
88
+ "Empty Molecule",
89
+ oedepict.OEFont(
90
+ oedepict.OEFontFamily_Arial,
91
+ oedepict.OEFontStyle_Normal,
92
+ 14,
93
+ oedepict.OEAlignment_Center,
94
+ oechem.OEDarkBlue
95
+ )
96
+ )
97
+
98
+ return create_img_tag(
99
+ ctx.min_width,
100
+ ctx.min_height,
101
+ image_mime_type=ctx.image_mime_type,
102
+ image_bytes=oedepict.OEWriteImageToString(ctx.image_format, image),
103
+ wrap_svg=ctx.structure_scale != oedepict.OEScale_AutoScale
104
+ )
105
+
106
+
107
+ def render_invalid_molecule(*, ctx: CNotebookContext) -> str:
108
+ """
109
+ Render an image that says Empty Molecule
110
+ :param ctx: Render context
111
+ :return: Image tag
112
+ """
113
+ image = oedepict.OEImage(ctx.min_width, ctx.min_height)
114
+ image.DrawText(
115
+ oedepict.OE2DPoint(ctx.min_width / 2, ctx.min_height / 2),
116
+ "Invalid Molecule",
117
+ oedepict.OEFont(
118
+ oedepict.OEFontFamily_Arial,
119
+ oedepict.OEFontStyle_Normal,
120
+ 14,
121
+ oedepict.OEAlignment_Center,
122
+ oechem.OERed
123
+ )
124
+ )
125
+
126
+ return create_img_tag(
127
+ ctx.min_width,
128
+ ctx.min_height,
129
+ image_mime_type=ctx.image_mime_type,
130
+ image_bytes=oedepict.OEWriteImageToString(ctx.image_format, image),
131
+ wrap_svg=ctx.structure_scale != oedepict.OEScale_AutoScale
132
+ )
133
+
134
+
135
+ def oemol_to_disp(
136
+ mol: oechem.OEMolBase,
137
+ *,
138
+ ctx: CNotebookContext
139
+ ) -> oedepict.OE2DMolDisplay:
140
+ """
141
+ Convert a valid OpenEye molecule object to a display object for depiction. Note that it is highly recommended to
142
+ test that the molecule is valid first before calling this function.
143
+ :param ctx: Render context
144
+ :param mol: Molecule to convert
145
+ :return: Display object for depiction
146
+ """
147
+ # Only recalculate coordinates if we don't have a 2D structure
148
+ if mol.GetDimension() == 2:
149
+ oedepict.OEPrepareDepiction(mol, False)
150
+ else:
151
+ oedepict.OEPrepareDepiction(mol, True)
152
+
153
+ return ctx.create_molecule_display(mol)
154
+
155
+
156
+ @pass_cnotebook_context
157
+ def oemol_to_html(mol: oechem.OEMolBase, *, ctx: CNotebookContext) -> str:
158
+ """
159
+ Convert an OpenEye Molecule object to HTML
160
+ :param ctx: Render context
161
+ :param mol: Molecule to convert
162
+ :return: HTML string
163
+ """
164
+ # Render valid molecules
165
+ if mol.IsValid():
166
+
167
+ # Create the display object from the context
168
+ disp = oemol_to_disp(mol, ctx=ctx)
169
+
170
+ # Render the display
171
+ return oedisp_to_html(disp, ctx=ctx)
172
+
173
+ # Render empty molecules
174
+ elif mol.NumAtoms() == 0:
175
+ return render_empty_molecule(ctx=ctx)
176
+
177
+ # Render other invalid molecules
178
+ else:
179
+ return render_invalid_molecule(ctx=ctx)
180
+
181
+
182
+ @pass_cnotebook_context
183
+ def oeimage_to_html(image: oedepict.OEImage, *, ctx: CNotebookContext) -> str:
184
+ """
185
+ Convert an OEImage to HTML
186
+ :param ctx: Render context
187
+ :param image: Image to render
188
+ :return: HTML string
189
+ """
190
+ # Convert the image to an <img> tag
191
+ image_bytes = oedepict.OEWriteImageToString(ctx.image_format, image)
192
+ return create_img_tag(
193
+ image.GetWidth(),
194
+ image.GetHeight(),
195
+ image_mime_type=ctx.image_mime_type,
196
+ image_bytes=image_bytes,
197
+ wrap_svg=ctx.structure_scale != oedepict.OEScale_AutoScale
198
+ )
@@ -0,0 +1,275 @@
1
+ Metadata-Version: 2.4
2
+ Name: cnotebook
3
+ Version: 1.0.1
4
+ Summary: Chemistry visualization in Jupyter Notebooks with the OpenEye Toolkits
5
+ Author-email: Scott Arne Johnson <scott.arne.johnson@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/scott-arne/cnotebook
8
+ Project-URL: Bug Reports, https://github.com/scott-arne/cnotebook/issues
9
+ Project-URL: Source, https://github.com/scott-arne/cnotebook
10
+ Project-URL: Documentation, https://github.com/scott-arne/cnotebook#readme
11
+ Project-URL: Changelog, https://github.com/scott-arne/cnotebook/blob/master/CHANGELOG.md
12
+ Keywords: chemistry,cheminformatics,computational-chemistry,molecular-visualization,jupyter,marimo,openeye,scientific-computing
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
17
+ Classifier: Topic :: Scientific/Engineering :: Visualization
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Operating System :: OS Independent
24
+ Classifier: Framework :: Jupyter
25
+ Classifier: Framework :: IPython
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: pandas<3.0.0,>=2.0.0
30
+ Requires-Dist: oepandas>=2.0.0
31
+ Requires-Dist: openeye-toolkits
32
+ Provides-Extra: dev
33
+ Requires-Dist: invoke; extra == "dev"
34
+ Requires-Dist: build; extra == "dev"
35
+ Requires-Dist: pytest; extra == "dev"
36
+ Provides-Extra: test
37
+ Requires-Dist: pytest; extra == "test"
38
+ Requires-Dist: pytest-cov; extra == "test"
39
+ Dynamic: license-file
40
+
41
+ # CNotebook - Chemistry Visualization for Jupyter & Marimo
42
+
43
+ **Author:** Scott Arne Johnson ([scott.arne.johnson@gmail.com](mailto:scott.arne.johnson@gmail.com))
44
+
45
+ CNotebook provides ergonomic chemistry visualization in Jupyter Notebooks and Marimo with the OpenEye Toolkits. Simply import the package and your molecular data will be automatically rendered as beautiful chemical structures - no additional configuration required!
46
+
47
+ ## 🚀 Quick Start
48
+
49
+ ### Installation
50
+
51
+ ```bash
52
+ pip install cnotebook
53
+ ```
54
+
55
+ **Prerequisites:** Requires OpenEye Toolkits and oepandas to be installed and properly licensed.
56
+
57
+ ### Basic Usage
58
+
59
+ ```python
60
+ import cnotebook
61
+ from openeye import oechem
62
+
63
+ # Create a molecule
64
+ mol = oechem.OEGraphMol()
65
+ oechem.OESmilesToMol(mol, "n1cnccc1")
66
+
67
+ # Display it - automatically renders as a chemical structure!
68
+ mol
69
+ ```
70
+
71
+ That's it! CNotebook automatically registers formatters so that OpenEye molecule objects display as chemical structures instead of cryptic text representations.
72
+
73
+ ## 📚 Features
74
+
75
+ ### ✨ Automatic Rendering
76
+ - **Zero Configuration**: Just import and go - molecules automatically render as structures
77
+ - **Multiple Formats**: Supports both Jupyter Notebooks and Marimo environments
78
+ - **Smart Detection**: Automatically detects your notebook environment
79
+
80
+ ### 🧪 Molecule Support
81
+ - **OEMol Objects**: Direct rendering of `oechem.OEMolBase` derived objects
82
+ - **OE2DMolDisplay**: Advanced rendering with custom depiction options
83
+ - **Pandas Integration**: Seamless rendering in DataFrames with oepandas
84
+
85
+ ### 🎨 Visualization Options
86
+ - **Multiple Formats**: PNG (default) or SVG output
87
+ - **Customizable Sizing**: Configurable width, height, and scaling
88
+ - **Grid Layouts**: Multi-molecule grid displays
89
+ - **Substructure Highlighting**: SMARTS pattern highlighting
90
+ - **Molecular Alignment**: Align molecules to reference structures
91
+
92
+ ### 📊 Pandas Integration
93
+ - **DataFrame Rendering**: Automatic molecule column detection and rendering
94
+ - **Column Highlighting**: Highlight different patterns per row
95
+ - **Alignment Tools**: Align molecular depictions in DataFrames
96
+ - **Fingerprint Similarity**: Visual similarity coloring
97
+ - **Property Calculation**: Chemistry-aware DataFrame operations
98
+
99
+ ## 🛠️ Environment Support
100
+
101
+ ### Jupyter Notebooks
102
+ CNotebook automatically integrates with Jupyter when imported:
103
+
104
+ ```python
105
+ import cnotebook
106
+ import pandas as pd
107
+ from openeye import oechem
108
+
109
+ # Molecules will automatically render in cells
110
+ mol = oechem.OEGraphMol()
111
+ oechem.OESmilesToMol(mol, "CCO")
112
+ mol # Displays as chemical structure
113
+ ```
114
+
115
+ ### Marimo
116
+ CNotebook provides seamless Marimo integration:
117
+
118
+ ```python
119
+ import marimo as mo
120
+ import cnotebook
121
+ from openeye import oechem
122
+
123
+ # Create and display molecules
124
+ mol = oechem.OEGraphMol()
125
+ oechem.OESmilesToMol(mol, "c1ccccc1")
126
+ mol # Automatically renders as PNG for Marimo compatibility
127
+ ```
128
+
129
+ ## 📖 Advanced Usage
130
+
131
+ ### Rendering Configuration
132
+
133
+ ```python
134
+ # Access global rendering context
135
+ ctx = cnotebook.cnotebook_context.get()
136
+
137
+ # Customize rendering options
138
+ ctx.width = 300
139
+ ctx.height = 300
140
+ ctx.image_format = "svg" # Use SVG instead of PNG
141
+ ctx.max_width = 600 # Prevent oversized molecules
142
+
143
+ # Reset to defaults
144
+ ctx.reset()
145
+ ```
146
+
147
+ ### Molecule Grids
148
+
149
+ ```python
150
+ # Display multiple molecules in a grid
151
+ molecules = [mol1, mol2, mol3, mol4]
152
+ cnotebook.render_molecule_grid(
153
+ molecules,
154
+ ncols=2,
155
+ smarts="c1ccccc1", # Highlight benzene rings
156
+ scale=0.8
157
+ )
158
+ ```
159
+
160
+ ### Pandas DataFrame Integration
161
+
162
+ ```python
163
+ import oepandas as oepd
164
+ import pandas as pd
165
+
166
+ # Create DataFrame with SMILES
167
+ df = pd.DataFrame({
168
+ "Name": ["Benzene", "Pyridine", "Pyrimidine"],
169
+ "SMILES": ["c1ccccc1", "c1cnccc1", "n1cnccc1"]
170
+ })
171
+
172
+ # Convert to molecules
173
+ df.as_molecule("SMILES", inplace=True)
174
+
175
+ # DataFrame automatically renders molecules as structures
176
+ df # Molecule column shows chemical structures!
177
+
178
+ # Add substructure highlighting
179
+ df.SMILES.highlight("c1ccccc1") # Highlight aromatic rings
180
+ df
181
+
182
+ # Align molecules to a reference
183
+ df.SMILES.align_depictions("first") # Align to first molecule
184
+ df
185
+ ```
186
+
187
+ ### Substructure Highlighting
188
+
189
+ ```python
190
+ # Highlight SMARTS patterns
191
+ df["Pattern"] = ["cc", "cnc", "ncn"]
192
+ df.highlight_using_column("Molecule", "Pattern", inplace=True)
193
+ df # Shows molecules with different highlights per row
194
+ ```
195
+
196
+ ### Fingerprint Similarity
197
+
198
+ ```python
199
+ # Color molecules by fingerprint similarity
200
+ reference_mol = oechem.OEGraphMol()
201
+ oechem.OESmilesToMol(reference_mol, "c1ccc(N)cc1")
202
+
203
+ df.fingerprint_similarity("Molecule", reference_mol, inplace=True)
204
+ df # Shows similarity coloring and Tanimoto coefficients
205
+ ```
206
+
207
+ ## 📁 Demo Notebooks
208
+
209
+ Explore comprehensive examples in the `demos/` directory:
210
+
211
+ ### [Small_Molecules.ipynb](demos/Small_Molecules.ipynb)
212
+ **Complete CNotebook Tutorial** - Comprehensive guide covering:
213
+ - Basic molecule rendering and display options
214
+ - OE2DMolDisplay objects with custom styling
215
+ - Molecule grid layouts with highlighting
216
+ - Advanced rendering configuration
217
+ - Pandas DataFrame integration with oepandas
218
+ - Substructure highlighting and SMARTS patterns
219
+ - Column-based highlighting with different patterns per row
220
+ - Molecular alignment techniques
221
+ - Fingerprint similarity visualization
222
+ - Empty and invalid molecule handling
223
+
224
+ ### [SVGs.ipynb](demos/SVGs.ipynb)
225
+ **SVG Rendering Guide** - Learn how to:
226
+ - Switch from PNG to SVG output format
227
+ - Benefits and trade-offs of SVG vs PNG
228
+ - High-quality crisp molecular graphics
229
+ - SVG compatibility considerations
230
+
231
+ ## 🔧 Configuration Options
232
+
233
+ ### Global Context Settings
234
+
235
+ ```python
236
+ ctx = cnotebook.cnotebook_context.get()
237
+
238
+ # Image dimensions
239
+ ctx.width = 250 # Default width in pixels
240
+ ctx.height = 250 # Default height in pixels
241
+ ctx.max_width = 1200 # Maximum width (prevents oversized molecules)
242
+ ctx.max_height = 800 # Maximum height
243
+
244
+ # Output format
245
+ ctx.image_format = "png" # or "svg"
246
+
247
+ # Display options
248
+ ctx.scale = 1.0 # Scaling factor
249
+ ```
250
+
251
+ ### Environment-Specific Behavior
252
+
253
+ - **Jupyter**: Supports both PNG and SVG formats
254
+ - **Marimo**: Automatically uses PNG format for compatibility
255
+ - **Console**: Falls back to string representations
256
+
257
+ ## 🤝 Contributing
258
+
259
+ We welcome contributions! Please ensure your code:
260
+ - Follows existing code style and conventions
261
+ - Includes appropriate tests
262
+ - Works with both Jupyter and Marimo environments
263
+ - Maintains compatibility with OpenEye Toolkits
264
+
265
+ ## 📄 License
266
+
267
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
268
+
269
+ ## 🐛 Issues & Support
270
+
271
+ For bug reports, feature requests, or general support, please open an issue on GitHub or contact the author at [scott.arne.johnson@gmail.com](mailto:scott.arne.johnson@gmail.com).
272
+
273
+ ---
274
+
275
+ *CNotebook makes chemical data visualization effortless. Import once, visualize everywhere!* 🧬✨
@@ -0,0 +1,13 @@
1
+ cnotebook/__init__.py,sha256=cdQtNy_bYo3ezhhLrSfQidCaRRAGVfqeIJA6XCh2wV0,2695
2
+ cnotebook/align.py,sha256=u22GEHJc8QzCb9If2mjuapKPOTBEB2iu6jtUfgmm1UQ,14086
3
+ cnotebook/context.py,sha256=MXOIIZ7PkWZ8Wi11L00ldAqsaNCBmJRc76bETelIq9w,17493
4
+ cnotebook/helpers.py,sha256=r5-CIcmomd8vbd6ILGU6uW3sAjWZPcng82cikZ0ZDZ8,2193
5
+ cnotebook/ipython_ext.py,sha256=T6kggGkT7YtDfW7XL3kM_wIhac9jVBQaeDgSrjlQp1g,8869
6
+ cnotebook/marimo_ext.py,sha256=b7TJU_Wj-UvfeCkvFWKzn28dPR4olbsd4auWG3UpzQ8,1055
7
+ cnotebook/pandas_ext.py,sha256=9ED28VrxOzdCELIpUpHminbUrccsNcqDFRMLNc26wVA,34795
8
+ cnotebook/render.py,sha256=N5W8-QQGD3d149K6E15MkUvnYtIyFeJ5o4Gphf8Bcuo,6141
9
+ cnotebook-1.0.1.dist-info/licenses/LICENSE,sha256=HbIgeZz-pWGC7BEnYFCQ-jfD1m_BfiosF9qjgWw64GU,1080
10
+ cnotebook-1.0.1.dist-info/METADATA,sha256=MvrUjSCF8Up_dJOF1dQ1pwlo_LZv0Ft9MStmFDPXQV4,8575
11
+ cnotebook-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ cnotebook-1.0.1.dist-info/top_level.txt,sha256=jzkieTjQwdNKfMwnoElvDDtNPkeLMjbvWbsbkSsboo8,10
13
+ cnotebook-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2025 Scott Arne Johnson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ cnotebook