cloudglancer 0.1.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AI@HHMI
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,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ recursive-include cloudglancer *.py py.typed
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloudglancer
3
+ Version: 0.1.0
4
+ Summary: Simple interactive visualization of 3D point clouds
5
+ Author-email: Your Name <your.email@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/cloudglancer
8
+ Project-URL: Repository, https://github.com/yourusername/cloudglancer
9
+ Project-URL: Issues, https://github.com/yourusername/cloudglancer/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Visualization
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: plotly>=5.0.0
24
+ Requires-Dist: pandas>=2.0.0
25
+ Requires-Dist: numpy>=1.24.0
26
+ Requires-Dist: nbformat>=4.2.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
29
+ Requires-Dist: black>=23.0.0; extra == "dev"
30
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # cloudglancer
34
+
35
+ Simple interactive visualization of 3D point clouds using Plotly.
36
+
37
+ ## Features
38
+
39
+ - Interactive 3D scatter plots with pan, zoom, and rotation
40
+ - Support for categorical and continuous color mapping
41
+ - Combine multiple plots into subplot grids
42
+ - Easy-to-use API with sensible defaults
43
+ - Type hints for better IDE support
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install cloudglancer
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ```python
54
+ import numpy as np
55
+ import cloudglancer
56
+
57
+ # Generate random 3D points
58
+ points = np.random.randn(500, 3)
59
+
60
+ # Create and display the plot
61
+ fig = cloudglancer.plot(points, title="My Point Cloud", size=2.0)
62
+ fig.show()
63
+ ```
64
+ More examples are in the `examples` folder.
65
+
66
+ ### Development Installation
67
+
68
+ Clone the repository and install in editable mode:
69
+
70
+ ```bash
71
+ git clone https://github.com/yourusername/cloudglancer.git
72
+ cd cloudglancer
73
+ python -m venv venv
74
+ source venv/bin/activate
75
+ pip install -e .
76
+ ```
77
+
78
+ ### Install with Development Dependencies
79
+
80
+ ```bash
81
+ pip install -e ".[dev]"
82
+ ```
83
+
84
+ ## Requirements
85
+
86
+ - Python >= 3.9
87
+ - plotly >= 5.0.0
88
+ - pandas >= 2.0.0
89
+ - numpy >= 1.24.0
90
+
91
+ ## API Reference
92
+
93
+ ### `cloudglancer.plot()`
94
+
95
+ Create an interactive 3D scatter plot.
96
+
97
+ **Parameters:**
98
+
99
+ - `points` (np.ndarray): Array of shape (n_points, 3) containing 3D coordinates.
100
+ - `labels` (np.ndarray, optional): Array of labels for color grouping.
101
+ - `label_map` (dict, optional): Maps label values to display names. Enables discrete color mapping.
102
+ - `color_map` (list or float, optional):
103
+ - With `label_map`: List of color strings for discrete coloring
104
+ - Without `label_map`: Float specifying the continuous color scale midpoint
105
+ - `size` (float, optional): Size of scatter plot markers. Default is 1.5.
106
+ - `title` (str, optional): Title of the plot.
107
+
108
+ **Returns:**
109
+
110
+ - `plotly.graph_objects.Figure`: Interactive 3D scatter plot.
111
+
112
+ **Raises:**
113
+
114
+ - `ValueError`: If points array is not of shape (n_points, 3).
115
+
116
+ ### `cloudglancer.combine_plots()`
117
+
118
+ Combine multiple 3D plots into a single figure with subplots.
119
+
120
+ **Parameters:**
121
+
122
+ - `figs` (list): List of Plotly figures to combine.
123
+ - `rows` (int, optional): Number of rows in the subplot grid. Default is 1.
124
+ - `cols` (int, optional): Number of columns in the subplot grid. Default is 2.
125
+
126
+ **Returns:**
127
+
128
+ - `plotly.graph_objects.Figure`: Combined figure with all plots arranged in a grid.
129
+
130
+ **Raises:**
131
+
132
+ - `ValueError`: If the number of figures doesn't match rows * cols.
133
+
134
+ ## Examples
135
+
136
+ See the [examples/](examples/) directory for more detailed usage examples.
137
+
138
+ Run the examples:
139
+
140
+ ```bash
141
+ python examples/basic_usage.py
142
+ ```
143
+
144
+ ## Development
145
+
146
+ ### Running Tests
147
+
148
+ ```bash
149
+ pytest tests/ -v
150
+ ```
151
+
152
+ ### Code Formatting
153
+
154
+ ```bash
155
+ black cloudglancer tests examples
156
+ ruff check cloudglancer tests examples
157
+ ```
158
+
159
+ ### Building the Package
160
+
161
+ ```bash
162
+ pip install build
163
+ python -m build
164
+ ```
165
+
166
+ This will create both wheel and source distributions in the `dist/` directory.
167
+
168
+ ## License
169
+
170
+ MIT License - see [LICENSE](LICENSE) file for details.
171
+
172
+ ## Contributing
173
+
174
+ Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,142 @@
1
+ # cloudglancer
2
+
3
+ Simple interactive visualization of 3D point clouds using Plotly.
4
+
5
+ ## Features
6
+
7
+ - Interactive 3D scatter plots with pan, zoom, and rotation
8
+ - Support for categorical and continuous color mapping
9
+ - Combine multiple plots into subplot grids
10
+ - Easy-to-use API with sensible defaults
11
+ - Type hints for better IDE support
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pip install cloudglancer
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```python
22
+ import numpy as np
23
+ import cloudglancer
24
+
25
+ # Generate random 3D points
26
+ points = np.random.randn(500, 3)
27
+
28
+ # Create and display the plot
29
+ fig = cloudglancer.plot(points, title="My Point Cloud", size=2.0)
30
+ fig.show()
31
+ ```
32
+ More examples are in the `examples` folder.
33
+
34
+ ### Development Installation
35
+
36
+ Clone the repository and install in editable mode:
37
+
38
+ ```bash
39
+ git clone https://github.com/yourusername/cloudglancer.git
40
+ cd cloudglancer
41
+ python -m venv venv
42
+ source venv/bin/activate
43
+ pip install -e .
44
+ ```
45
+
46
+ ### Install with Development Dependencies
47
+
48
+ ```bash
49
+ pip install -e ".[dev]"
50
+ ```
51
+
52
+ ## Requirements
53
+
54
+ - Python >= 3.9
55
+ - plotly >= 5.0.0
56
+ - pandas >= 2.0.0
57
+ - numpy >= 1.24.0
58
+
59
+ ## API Reference
60
+
61
+ ### `cloudglancer.plot()`
62
+
63
+ Create an interactive 3D scatter plot.
64
+
65
+ **Parameters:**
66
+
67
+ - `points` (np.ndarray): Array of shape (n_points, 3) containing 3D coordinates.
68
+ - `labels` (np.ndarray, optional): Array of labels for color grouping.
69
+ - `label_map` (dict, optional): Maps label values to display names. Enables discrete color mapping.
70
+ - `color_map` (list or float, optional):
71
+ - With `label_map`: List of color strings for discrete coloring
72
+ - Without `label_map`: Float specifying the continuous color scale midpoint
73
+ - `size` (float, optional): Size of scatter plot markers. Default is 1.5.
74
+ - `title` (str, optional): Title of the plot.
75
+
76
+ **Returns:**
77
+
78
+ - `plotly.graph_objects.Figure`: Interactive 3D scatter plot.
79
+
80
+ **Raises:**
81
+
82
+ - `ValueError`: If points array is not of shape (n_points, 3).
83
+
84
+ ### `cloudglancer.combine_plots()`
85
+
86
+ Combine multiple 3D plots into a single figure with subplots.
87
+
88
+ **Parameters:**
89
+
90
+ - `figs` (list): List of Plotly figures to combine.
91
+ - `rows` (int, optional): Number of rows in the subplot grid. Default is 1.
92
+ - `cols` (int, optional): Number of columns in the subplot grid. Default is 2.
93
+
94
+ **Returns:**
95
+
96
+ - `plotly.graph_objects.Figure`: Combined figure with all plots arranged in a grid.
97
+
98
+ **Raises:**
99
+
100
+ - `ValueError`: If the number of figures doesn't match rows * cols.
101
+
102
+ ## Examples
103
+
104
+ See the [examples/](examples/) directory for more detailed usage examples.
105
+
106
+ Run the examples:
107
+
108
+ ```bash
109
+ python examples/basic_usage.py
110
+ ```
111
+
112
+ ## Development
113
+
114
+ ### Running Tests
115
+
116
+ ```bash
117
+ pytest tests/ -v
118
+ ```
119
+
120
+ ### Code Formatting
121
+
122
+ ```bash
123
+ black cloudglancer tests examples
124
+ ruff check cloudglancer tests examples
125
+ ```
126
+
127
+ ### Building the Package
128
+
129
+ ```bash
130
+ pip install build
131
+ python -m build
132
+ ```
133
+
134
+ This will create both wheel and source distributions in the `dist/` directory.
135
+
136
+ ## License
137
+
138
+ MIT License - see [LICENSE](LICENSE) file for details.
139
+
140
+ ## Contributing
141
+
142
+ Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,6 @@
1
+ """cloudglancer: Simple interactive visualization of 3D point clouds"""
2
+
3
+ from cloudglancer.scatter import plot, combine_plots
4
+
5
+ __version__ = "0.1.0"
6
+ __all__ = ["plot", "combine_plots"]
@@ -0,0 +1,129 @@
1
+ """Core scatter plotting functionality for 3D point clouds."""
2
+
3
+ from typing import Optional, List, Dict, Union
4
+ import plotly.express as px
5
+ import pandas as pd
6
+ import numpy as np
7
+ from plotly.graph_objects import Figure
8
+
9
+
10
+ def plot(
11
+ points: np.ndarray,
12
+ labels: Optional[np.ndarray] = None,
13
+ label_map: Optional[Dict] = None,
14
+ color_map: Optional[Union[List[str], float]] = None,
15
+ size: float = 1.5,
16
+ title: Optional[str] = None
17
+ ) -> Figure:
18
+ """
19
+ Render an interactive 3D scatter plot using Plotly.
20
+
21
+ Args:
22
+ points (np.ndarray): Array of shape (n_points, 3) containing 3D coordinates.
23
+ labels (np.ndarray, optional): Array of labels for color grouping. When provided
24
+ with label_map, enables discrete color mapping. Without label_map, creates
25
+ a continuous color scale.
26
+ label_map (dict, optional): Maps label values to display names. When provided,
27
+ enables discrete color mapping.
28
+ color_map (list or float, optional): When label_map is provided, this should be
29
+ a list of color strings for discrete coloring. Without label_map, this can be
30
+ a float specifying the continuous color scale midpoint.
31
+ size (float, optional): Size of the scatter plot markers. Default is 1.5.
32
+ title (str, optional): Title of the plot.
33
+
34
+ Returns:
35
+ plotly.graph_objects.Figure: Interactive 3D scatter plot.
36
+
37
+ Raises:
38
+ ValueError: If points array is not of shape (n_points, 3).
39
+
40
+ Examples:
41
+ Basic scatter plot:
42
+ >>> import numpy as np
43
+ >>> points = np.random.randn(100, 3)
44
+ >>> fig = plot(points, title="Random Points")
45
+ >>> fig.show()
46
+
47
+ Plot with categorical labels:
48
+ >>> labels = np.random.choice([0, 1, 2], size=100)
49
+ >>> label_map = {0: "Class A", 1: "Class B", 2: "Class C"}
50
+ >>> color_map = ["red", "blue", "green"]
51
+ >>> fig = plot(points, labels=labels, label_map=label_map, color_map=color_map)
52
+ >>> fig.show()
53
+ """
54
+ if points.shape[1] != 3:
55
+ raise ValueError("points must be of shape (n_points, 3)")
56
+
57
+ # Create a DataFrame for easier plotting
58
+ df = pd.DataFrame(points, columns=["x", "y", "z"])
59
+
60
+ if labels is not None:
61
+ df["label"] = labels
62
+ if label_map:
63
+ df["label"] = df["label"].map(label_map).fillna(df["label"])
64
+ fig = px.scatter_3d(df, x="x", y="y", z="z", color="label",
65
+ color_discrete_sequence=color_map)
66
+ else:
67
+ fig = px.scatter_3d(df, x="x", y="y", z="z", color="label",
68
+ color_continuous_midpoint=color_map, range_color=[0, 1])
69
+ else:
70
+ fig = px.scatter_3d(df, x="x", y="y", z="z")
71
+
72
+ fig.update_traces(marker=dict(size=size))
73
+
74
+ # Fix: Apply title if provided
75
+ if title:
76
+ fig.update_layout(title=title)
77
+
78
+ return fig
79
+
80
+
81
+ def combine_plots(figs: List[Figure], rows: int = 1, cols: int = 2) -> Figure:
82
+ """
83
+ Combine multiple 3D plots into a single figure with subplots.
84
+
85
+ Args:
86
+ figs (list): List of Plotly figures to combine.
87
+ rows (int, optional): Number of rows in the subplot grid. Default is 1.
88
+ cols (int, optional): Number of columns in the subplot grid. Default is 2.
89
+
90
+ Returns:
91
+ plotly.graph_objects.Figure: Combined figure with all plots arranged in a grid.
92
+
93
+ Raises:
94
+ ValueError: If the number of figures doesn't match rows * cols.
95
+
96
+ Examples:
97
+ Combine two plots side by side:
98
+ >>> points1 = np.random.randn(100, 3)
99
+ >>> points2 = np.random.randn(100, 3) + 5
100
+ >>> fig1 = plot(points1, title="Dataset 1")
101
+ >>> fig2 = plot(points2, title="Dataset 2")
102
+ >>> combined = combine_plots([fig1, fig2], rows=1, cols=2)
103
+ >>> combined.show()
104
+ """
105
+ from plotly.subplots import make_subplots
106
+
107
+ # Fix: Validate figure count
108
+ if len(figs) != rows * cols:
109
+ raise ValueError(
110
+ f"Number of figures ({len(figs)}) must equal rows * cols ({rows * cols})"
111
+ )
112
+
113
+ # Fix: Generate specs dynamically based on rows and cols
114
+ specs = [[{"type": "scene"} for _ in range(cols)] for _ in range(rows)]
115
+
116
+ combined_fig = make_subplots(
117
+ rows=rows, cols=cols,
118
+ specs=specs
119
+ )
120
+
121
+ for i, fig in enumerate(figs):
122
+ for trace in fig.data:
123
+ combined_fig.add_trace(trace, row=(i // cols) + 1, col=(i % cols) + 1)
124
+
125
+ combined_fig.update_layout(
126
+ margin=dict(l=0, r=0, t=0, b=0)
127
+ )
128
+
129
+ return combined_fig
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloudglancer
3
+ Version: 0.1.0
4
+ Summary: Simple interactive visualization of 3D point clouds
5
+ Author-email: Your Name <your.email@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/cloudglancer
8
+ Project-URL: Repository, https://github.com/yourusername/cloudglancer
9
+ Project-URL: Issues, https://github.com/yourusername/cloudglancer/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Visualization
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: plotly>=5.0.0
24
+ Requires-Dist: pandas>=2.0.0
25
+ Requires-Dist: numpy>=1.24.0
26
+ Requires-Dist: nbformat>=4.2.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
29
+ Requires-Dist: black>=23.0.0; extra == "dev"
30
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # cloudglancer
34
+
35
+ Simple interactive visualization of 3D point clouds using Plotly.
36
+
37
+ ## Features
38
+
39
+ - Interactive 3D scatter plots with pan, zoom, and rotation
40
+ - Support for categorical and continuous color mapping
41
+ - Combine multiple plots into subplot grids
42
+ - Easy-to-use API with sensible defaults
43
+ - Type hints for better IDE support
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install cloudglancer
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ```python
54
+ import numpy as np
55
+ import cloudglancer
56
+
57
+ # Generate random 3D points
58
+ points = np.random.randn(500, 3)
59
+
60
+ # Create and display the plot
61
+ fig = cloudglancer.plot(points, title="My Point Cloud", size=2.0)
62
+ fig.show()
63
+ ```
64
+ More examples are in the `examples` folder.
65
+
66
+ ### Development Installation
67
+
68
+ Clone the repository and install in editable mode:
69
+
70
+ ```bash
71
+ git clone https://github.com/yourusername/cloudglancer.git
72
+ cd cloudglancer
73
+ python -m venv venv
74
+ source venv/bin/activate
75
+ pip install -e .
76
+ ```
77
+
78
+ ### Install with Development Dependencies
79
+
80
+ ```bash
81
+ pip install -e ".[dev]"
82
+ ```
83
+
84
+ ## Requirements
85
+
86
+ - Python >= 3.9
87
+ - plotly >= 5.0.0
88
+ - pandas >= 2.0.0
89
+ - numpy >= 1.24.0
90
+
91
+ ## API Reference
92
+
93
+ ### `cloudglancer.plot()`
94
+
95
+ Create an interactive 3D scatter plot.
96
+
97
+ **Parameters:**
98
+
99
+ - `points` (np.ndarray): Array of shape (n_points, 3) containing 3D coordinates.
100
+ - `labels` (np.ndarray, optional): Array of labels for color grouping.
101
+ - `label_map` (dict, optional): Maps label values to display names. Enables discrete color mapping.
102
+ - `color_map` (list or float, optional):
103
+ - With `label_map`: List of color strings for discrete coloring
104
+ - Without `label_map`: Float specifying the continuous color scale midpoint
105
+ - `size` (float, optional): Size of scatter plot markers. Default is 1.5.
106
+ - `title` (str, optional): Title of the plot.
107
+
108
+ **Returns:**
109
+
110
+ - `plotly.graph_objects.Figure`: Interactive 3D scatter plot.
111
+
112
+ **Raises:**
113
+
114
+ - `ValueError`: If points array is not of shape (n_points, 3).
115
+
116
+ ### `cloudglancer.combine_plots()`
117
+
118
+ Combine multiple 3D plots into a single figure with subplots.
119
+
120
+ **Parameters:**
121
+
122
+ - `figs` (list): List of Plotly figures to combine.
123
+ - `rows` (int, optional): Number of rows in the subplot grid. Default is 1.
124
+ - `cols` (int, optional): Number of columns in the subplot grid. Default is 2.
125
+
126
+ **Returns:**
127
+
128
+ - `plotly.graph_objects.Figure`: Combined figure with all plots arranged in a grid.
129
+
130
+ **Raises:**
131
+
132
+ - `ValueError`: If the number of figures doesn't match rows * cols.
133
+
134
+ ## Examples
135
+
136
+ See the [examples/](examples/) directory for more detailed usage examples.
137
+
138
+ Run the examples:
139
+
140
+ ```bash
141
+ python examples/basic_usage.py
142
+ ```
143
+
144
+ ## Development
145
+
146
+ ### Running Tests
147
+
148
+ ```bash
149
+ pytest tests/ -v
150
+ ```
151
+
152
+ ### Code Formatting
153
+
154
+ ```bash
155
+ black cloudglancer tests examples
156
+ ruff check cloudglancer tests examples
157
+ ```
158
+
159
+ ### Building the Package
160
+
161
+ ```bash
162
+ pip install build
163
+ python -m build
164
+ ```
165
+
166
+ This will create both wheel and source distributions in the `dist/` directory.
167
+
168
+ ## License
169
+
170
+ MIT License - see [LICENSE](LICENSE) file for details.
171
+
172
+ ## Contributing
173
+
174
+ Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ cloudglancer/__init__.py
6
+ cloudglancer/scatter.py
7
+ cloudglancer.egg-info/PKG-INFO
8
+ cloudglancer.egg-info/SOURCES.txt
9
+ cloudglancer.egg-info/dependency_links.txt
10
+ cloudglancer.egg-info/requires.txt
11
+ cloudglancer.egg-info/top_level.txt
12
+ tests/test_scatter.py
@@ -0,0 +1,9 @@
1
+ plotly>=5.0.0
2
+ pandas>=2.0.0
3
+ numpy>=1.24.0
4
+ nbformat>=4.2.0
5
+
6
+ [dev]
7
+ pytest>=7.0.0
8
+ black>=23.0.0
9
+ ruff>=0.1.0
@@ -0,0 +1 @@
1
+ cloudglancer
@@ -0,0 +1,58 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cloudglancer"
7
+ version = "0.1.0"
8
+ description = "Simple interactive visualization of 3D point clouds"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Your Name", email = "your.email@example.com"}
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Science/Research",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Scientific/Engineering :: Visualization",
26
+ ]
27
+ dependencies = [
28
+ "plotly>=5.0.0",
29
+ "pandas>=2.0.0",
30
+ "numpy>=1.24.0",
31
+ "nbformat>=4.2.0",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ dev = [
36
+ "pytest>=7.0.0",
37
+ "black>=23.0.0",
38
+ "ruff>=0.1.0",
39
+ ]
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/yourusername/cloudglancer"
43
+ Repository = "https://github.com/yourusername/cloudglancer"
44
+ Issues = "https://github.com/yourusername/cloudglancer/issues"
45
+
46
+ [tool.setuptools.packages.find]
47
+ include = ["cloudglancer*"]
48
+
49
+ [tool.setuptools.package-data]
50
+ cloudglancer = ["py.typed"]
51
+
52
+ [tool.black]
53
+ line-length = 100
54
+ target-version = ["py39"]
55
+
56
+ [tool.ruff]
57
+ line-length = 100
58
+ target-version = "py39"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,91 @@
1
+ """Unit tests for cloudglancer.scatter module."""
2
+
3
+ import numpy as np
4
+ import pytest
5
+ from cloudglancer import plot, combine_plots
6
+
7
+
8
+ def test_plot_basic():
9
+ """Test basic plot creation with random points."""
10
+ points = np.random.randn(100, 3)
11
+ fig = plot(points)
12
+ assert fig is not None
13
+ assert len(fig.data) == 1
14
+ assert fig.data[0].type == "scatter3d"
15
+
16
+
17
+ def test_plot_with_labels():
18
+ """Test plot with continuous labels."""
19
+ points = np.random.randn(100, 3)
20
+ labels = np.random.rand(100)
21
+ fig = plot(points, labels=labels)
22
+ assert fig is not None
23
+ assert len(fig.data) == 1
24
+
25
+
26
+ def test_plot_with_label_map():
27
+ """Test plot with discrete color mapping."""
28
+ points = np.random.randn(100, 3)
29
+ labels = np.random.choice([0, 1, 2], size=100)
30
+ label_map = {0: "Class A", 1: "Class B", 2: "Class C"}
31
+ color_map = ["red", "blue", "green"]
32
+ fig = plot(points, labels=labels, label_map=label_map, color_map=color_map)
33
+ assert fig is not None
34
+ assert len(fig.data) > 0
35
+
36
+
37
+ def test_plot_invalid_shape():
38
+ """Test that ValueError is raised for incorrect point shape."""
39
+ points = np.random.randn(100, 2) # Wrong shape
40
+ with pytest.raises(ValueError, match="points must be of shape"):
41
+ plot(points)
42
+
43
+
44
+ def test_plot_title():
45
+ """Test that title is correctly applied to the figure."""
46
+ points = np.random.randn(100, 3)
47
+ title = "Test Plot Title"
48
+ fig = plot(points, title=title)
49
+ assert fig.layout.title.text == title
50
+
51
+
52
+ def test_plot_title_none():
53
+ """Test that plot works without a title."""
54
+ points = np.random.randn(100, 3)
55
+ fig = plot(points, title=None)
56
+ assert fig is not None
57
+
58
+
59
+ def test_combine_plots():
60
+ """Test combining multiple plots."""
61
+ points1 = np.random.randn(50, 3)
62
+ points2 = np.random.randn(50, 3)
63
+ fig1 = plot(points1)
64
+ fig2 = plot(points2)
65
+ combined = combine_plots([fig1, fig2], rows=1, cols=2)
66
+ assert combined is not None
67
+ assert len(combined.data) == 2
68
+
69
+
70
+ def test_combine_plots_grid():
71
+ """Test combining plots in a 2x2 grid."""
72
+ figs = [plot(np.random.randn(30, 3)) for _ in range(4)]
73
+ combined = combine_plots(figs, rows=2, cols=2)
74
+ assert combined is not None
75
+ assert len(combined.data) == 4
76
+
77
+
78
+ def test_combine_plots_invalid_count():
79
+ """Test that ValueError is raised when figure count doesn't match grid."""
80
+ fig1 = plot(np.random.randn(50, 3))
81
+ fig2 = plot(np.random.randn(50, 3))
82
+ with pytest.raises(ValueError, match="Number of figures"):
83
+ combine_plots([fig1, fig2], rows=2, cols=2) # 2 figs, but 2x2 = 4 spaces
84
+
85
+
86
+ def test_plot_size_parameter():
87
+ """Test that marker size parameter is applied."""
88
+ points = np.random.randn(100, 3)
89
+ size = 3.0
90
+ fig = plot(points, size=size)
91
+ assert fig.data[0].marker.size == size