dva-lab 0.1.0__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.
dva_lab/__init__.py ADDED
@@ -0,0 +1,87 @@
1
+ """dva-lab: Data Visualization and Analytics Laboratory Python Package.
2
+
3
+ A self-contained Python library for retrieving, displaying, and executing
4
+ DVA lab experiments directly inside Jupyter Notebook, JupyterLab, and Google Colab.
5
+ """
6
+
7
+ from .core import (
8
+ list_experiments,
9
+ show_experiment,
10
+ get_code,
11
+ show_code,
12
+ code,
13
+ run_experiment,
14
+ exp1,
15
+ exp2,
16
+ exp3,
17
+ exp4,
18
+ exp5,
19
+ exp6,
20
+ exp7,
21
+ exp8,
22
+ exp9,
23
+ exp10,
24
+ exp11,
25
+ exp12,
26
+ code1,
27
+ code2,
28
+ code3,
29
+ code4,
30
+ code5,
31
+ code6,
32
+ code7,
33
+ code8,
34
+ code9,
35
+ code10,
36
+ code11,
37
+ code12,
38
+ about,
39
+ help,
40
+ )
41
+ from .experiments.exp10_powerbi_visualization import (
42
+ get_sales_data_path,
43
+ load_sales_data,
44
+ )
45
+ from .registry import registry
46
+
47
+ __version__ = "0.1.0"
48
+ __author__ = "DVA Lab"
49
+
50
+ __all__ = [
51
+ "list_experiments",
52
+ "show_experiment",
53
+ "get_code",
54
+ "show_code",
55
+ "run_experiment",
56
+ "exp1",
57
+ "exp2",
58
+ "exp3",
59
+ "exp4",
60
+ "exp5",
61
+ "exp6",
62
+ "exp7",
63
+ "exp8",
64
+ "exp9",
65
+ "exp10",
66
+ "exp11",
67
+ "exp12",
68
+ "code",
69
+ "code1",
70
+ "code2",
71
+ "code3",
72
+ "code4",
73
+ "code5",
74
+ "code6",
75
+ "code7",
76
+ "code8",
77
+ "code9",
78
+ "code10",
79
+ "code11",
80
+ "code12",
81
+ "about",
82
+ "help",
83
+ "load_sales_data",
84
+ "get_sales_data_path",
85
+ "registry",
86
+ "__version__",
87
+ ]
dva_lab/core.py ADDED
@@ -0,0 +1,364 @@
1
+ """Core public API functions and Jupyter display utilities for dva_lab."""
2
+
3
+ import sys
4
+ from typing import Any, Optional, Dict
5
+ from .registry import registry, ExperimentList
6
+ from .experiments.base import Experiment
7
+
8
+
9
+ def is_jupyter() -> bool:
10
+ """Check if the code is executing inside an interactive Jupyter / IPython environment."""
11
+ try:
12
+ from IPython import get_ipython
13
+ ip = get_ipython()
14
+ if ip is None:
15
+ return False
16
+ # Running in IPython shell, notebook, lab, or Colab
17
+ if "IPKernelApp" in ip.config or "google.colab" in str(type(ip)):
18
+ return True
19
+ return hasattr(ip, "kernel")
20
+ except Exception:
21
+ return False
22
+
23
+
24
+ def list_experiments() -> ExperimentList:
25
+ """List all 12 DVA laboratory experiments.
26
+
27
+ In Jupyter Notebooks, renders a styled table with experiment numbers, titles,
28
+ categories, and aims. Outside Jupyter, returns a formatted text table.
29
+ Can also be converted to a pandas DataFrame via `.to_dataframe()`.
30
+ """
31
+ return registry.all()
32
+
33
+
34
+ def show_experiment(number: int) -> str:
35
+ """Display the aim, concept, source code, dependencies, and expected output.
36
+
37
+ Renders styled Markdown in Jupyter Notebook / Colab, or prints formatted text
38
+ in standard terminal environments.
39
+
40
+ Args:
41
+ number: Experiment index from 1 to 12.
42
+
43
+ Returns:
44
+ The markdown formatted text representation.
45
+
46
+ Raises:
47
+ ValueError: If number is not an integer between 1 and 12.
48
+ """
49
+ exp = registry.get(number)
50
+
51
+ # Format code fence according to category
52
+ lang = "sql" if "SQL" in exp.category else ("python" if "Python" in exp.category else "text")
53
+
54
+ dep_badges = ", ".join(f"`{d}`" for d in exp.dependencies)
55
+
56
+ md = f"""# Experiment {exp.number}: {exp.title}
57
+
58
+ > **Category**: {exp.category}
59
+ > **Required Dependencies**: {dep_badges}
60
+
61
+ ---
62
+
63
+ ### Aim
64
+ {exp.aim}
65
+
66
+ ### Concept & Methodology
67
+ {exp.concept}
68
+
69
+ ### Complete Source Code
70
+ ```{lang}
71
+ {exp.code.strip()}
72
+ ```
73
+
74
+ ### Expected Output
75
+ ```text
76
+ {exp.expected_output.strip()}
77
+ ```
78
+
79
+ ### Result Statement
80
+ *{exp.result}*
81
+
82
+ ---
83
+ ### Execution Notes & Instructions
84
+ {exp.notes}
85
+ """
86
+
87
+ if is_jupyter():
88
+ try:
89
+ from IPython.display import display, Markdown
90
+ display(Markdown(md))
91
+ return md
92
+ except Exception:
93
+ pass
94
+
95
+ print(md)
96
+ return md
97
+
98
+
99
+ class CodeString(str):
100
+ """String subclass that renders with syntax highlighting in Jupyter Notebook."""
101
+
102
+ def __new__(cls, content: str, language: str = "python"):
103
+ obj = super().__new__(cls, content)
104
+ obj.language = language
105
+ return obj
106
+
107
+ def _repr_markdown_(self) -> str:
108
+ """Render syntax-highlighted code block in Jupyter."""
109
+ return f"```{self.language}\n{self}\n```"
110
+
111
+ def __repr__(self) -> str:
112
+ return str(self)
113
+
114
+
115
+ def get_code(number: int) -> CodeString:
116
+ """Return the raw, complete source code for an experiment as a CodeString.
117
+
118
+ In Jupyter Notebooks, renders as a syntax-highlighted code block that can be
119
+ easily read, selected, and copied.
120
+
121
+ Args:
122
+ number: Experiment index from 1 to 12.
123
+
124
+ Returns:
125
+ CodeString containing the complete source code.
126
+
127
+ Raises:
128
+ ValueError: If number is not an integer between 1 and 12.
129
+ """
130
+ exp = registry.get(number)
131
+ lang = "sql" if "SQL" in exp.category else ("python" if "Python" in exp.category else "text")
132
+ return CodeString(exp.code, language=lang)
133
+
134
+
135
+ def show_code(number: int) -> CodeString:
136
+ """Display the raw source code for an experiment with syntax highlighting.
137
+
138
+ Args:
139
+ number: Experiment index from 1 to 12.
140
+
141
+ Returns:
142
+ CodeString for copying or programmatic use.
143
+ """
144
+ code = get_code(number)
145
+ if is_jupyter():
146
+ try:
147
+ from IPython.display import display, Markdown
148
+ display(Markdown(f"```{code.language}\n{code}\n```"))
149
+ return code
150
+ except Exception:
151
+ pass
152
+ print(code)
153
+ return code
154
+
155
+
156
+ def run_experiment(number: int, **kwargs) -> Any:
157
+ """Execute a compatible experiment or display its execution instructions.
158
+
159
+ - Experiments 3 to 9 (Python): Renders inline Matplotlib/Seaborn plots in Jupyter.
160
+ - Experiments 1 and 2 (SQL): Displays PostgreSQL scripts & instructions (safe execution).
161
+ - Experiments 10 to 12 (Power BI): Displays report construction guide & DAX analysis.
162
+
163
+ Special Arguments:
164
+ code=True (or show_code=True): Display and return source code instead of running.
165
+
166
+ Args:
167
+ number: Experiment index from 1 to 12.
168
+ **kwargs: Optional keyword arguments passed to the experiment runner.
169
+
170
+ Returns:
171
+ The result of the experiment runner (figures for Python, script for SQL/Power BI).
172
+
173
+ Raises:
174
+ ValueError: If number is not an integer between 1 and 12.
175
+ """
176
+ if kwargs.get("code") or kwargs.get("show_code"):
177
+ return show_code(number)
178
+
179
+ exp = registry.get(number)
180
+ return exp.run(**kwargs)
181
+
182
+
183
+ # ----------------------------------------------------------------------------
184
+ # Shortcut Functions (exp1 through exp12)
185
+ # ----------------------------------------------------------------------------
186
+
187
+ def exp1(**kwargs) -> Any:
188
+ """Shortcut: Experiment 1 - OLAP operations using materialized views (PostgreSQL)."""
189
+ return run_experiment(1, **kwargs)
190
+
191
+
192
+ def exp2(**kwargs) -> Any:
193
+ """Shortcut: Experiment 2 - OLAP operations using Star schema materialized views (PostgreSQL)."""
194
+ return run_experiment(2, **kwargs)
195
+
196
+
197
+ def exp3(**kwargs) -> Any:
198
+ """Shortcut: Experiment 3 - Vertical and horizontal bar charts (Python)."""
199
+ return run_experiment(3, **kwargs)
200
+
201
+
202
+ def exp4(**kwargs) -> Any:
203
+ """Shortcut: Experiment 4 - Grouped and stacked bar charts (Python)."""
204
+ return run_experiment(4, **kwargs)
205
+
206
+
207
+ def exp5(**kwargs) -> Any:
208
+ """Shortcut: Experiment 5 - Single and multiple variable histograms (Python)."""
209
+ return run_experiment(5, **kwargs)
210
+
211
+
212
+ def exp6(**kwargs) -> Any:
213
+ """Shortcut: Experiment 6 - Single and multiple variable density plots (Python)."""
214
+ return run_experiment(6, **kwargs)
215
+
216
+
217
+ def exp7(**kwargs) -> Any:
218
+ """Shortcut: Experiment 7 - Empirical Cumulative Distribution Function (ECDF) plot (Python)."""
219
+ return run_experiment(7, **kwargs)
220
+
221
+
222
+ def exp8(**kwargs) -> Any:
223
+ """Shortcut: Experiment 8 - Q-Q plot to compare two datasets (Python)."""
224
+ return run_experiment(8, **kwargs)
225
+
226
+
227
+ def exp9(**kwargs) -> Any:
228
+ """Shortcut: Experiment 9 - Scatter plot using sample data (Python)."""
229
+ return run_experiment(9, **kwargs)
230
+
231
+
232
+ def exp10(**kwargs) -> Any:
233
+ """Shortcut: Experiment 10 - Power BI sales data visualization."""
234
+ return run_experiment(10, **kwargs)
235
+
236
+
237
+ def exp11(**kwargs) -> Any:
238
+ """Shortcut: Experiment 11 - Power BI sales calculations and DAX measures."""
239
+ return run_experiment(11, **kwargs)
240
+
241
+
242
+ def exp12(**kwargs) -> Any:
243
+ """Shortcut: Experiment 12 - Power BI conditional & logical analysis (IF, AND, OR)."""
244
+ return run_experiment(12, **kwargs)
245
+
246
+
247
+ # ----------------------------------------------------------------------------
248
+ # Code-only Shortcuts (code1 through code12 and code())
249
+ # ----------------------------------------------------------------------------
250
+
251
+ code = show_code
252
+
253
+
254
+ def code1() -> CodeString:
255
+ """Shortcut: Print and return source code for Experiment 1 (PostgreSQL OLAP)."""
256
+ return show_code(1)
257
+
258
+
259
+ def code2() -> CodeString:
260
+ """Shortcut: Print and return source code for Experiment 2 (Star Schema OLAP)."""
261
+ return show_code(2)
262
+
263
+
264
+ def code3() -> CodeString:
265
+ """Shortcut: Print and return source code for Experiment 3 (Vertical & Horizontal Bar Charts)."""
266
+ return show_code(3)
267
+
268
+
269
+ def code4() -> CodeString:
270
+ """Shortcut: Print and return source code for Experiment 4 (Grouped & Stacked Bar Charts)."""
271
+ return show_code(4)
272
+
273
+
274
+ def code5() -> CodeString:
275
+ """Shortcut: Print and return source code for Experiment 5 (Single & Multi-Variable Histograms)."""
276
+ return show_code(5)
277
+
278
+
279
+ def code6() -> CodeString:
280
+ """Shortcut: Print and return source code for Experiment 6 (Single & Multi-Variable Density Plots)."""
281
+ return show_code(6)
282
+
283
+
284
+ def code7() -> CodeString:
285
+ """Shortcut: Print and return source code for Experiment 7 (ECDF Plot)."""
286
+ return show_code(7)
287
+
288
+
289
+ def code8() -> CodeString:
290
+ """Shortcut: Print and return source code for Experiment 8 (Q-Q Plot)."""
291
+ return show_code(8)
292
+
293
+
294
+ def code9() -> CodeString:
295
+ """Shortcut: Print and return source code for Experiment 9 (Scatter Plot)."""
296
+ return show_code(9)
297
+
298
+
299
+ def code10() -> CodeString:
300
+ """Shortcut: Print and return source code / procedure for Experiment 10 (Power BI Sales Visuals)."""
301
+ return show_code(10)
302
+
303
+
304
+ def code11() -> CodeString:
305
+ """Shortcut: Print and return source code / DAX for Experiment 11 (Power BI DAX Measures)."""
306
+ return show_code(11)
307
+
308
+
309
+ def code12() -> CodeString:
310
+ """Shortcut: Print and return source code / DAX for Experiment 12 (Power BI Logic IF/AND/OR)."""
311
+ return show_code(12)
312
+
313
+
314
+ def about() -> None:
315
+ """Display library overview, version, and quick reference guide."""
316
+ from . import __version__
317
+ text = f"""
318
+ ================================================================================
319
+ dva-lab (v{__version__}) - Data Visualization and Analytics Laboratory Library
320
+ ================================================================================
321
+ A self-contained Python package empowering students to retrieve, display, and
322
+ execute Data Visualization and Analytics (DVA) experiments inside Jupyter Notebook.
323
+
324
+ Public API:
325
+ - dva_lab.list_experiments() : List all 12 experiments with metadata
326
+ - dva_lab.show_experiment(n) : Display full experiment guide in Markdown
327
+ - dva_lab.get_code(n) : Retrieve raw source code as a string
328
+ - dva_lab.run_experiment(n) : Execute Python plots or show SQL/Power BI guides
329
+ - dva_lab.exp1() ... exp12() : Fast convenience shortcuts
330
+ - dva_lab.load_sales_data() : Load bundled sales_data.csv as DataFrame
331
+ - dva_lab.about() : Show this help guide
332
+
333
+ Experiments Catalog:
334
+ [SQL / OLAP]
335
+ 1. OLAP Operations Using Materialized Views
336
+ 2. OLAP Operations Using Materialized Views (Star Schema)
337
+ [Python Visualizations]
338
+ 3. Vertical and Horizontal Bar Charts
339
+ 4. Grouped and Stacked Bar Charts
340
+ 5. Single and Multiple Variable Histograms
341
+ 6. Single and Multiple Variable Density Plots
342
+ 7. Empirical Cumulative Distribution Function (ECDF) Plot
343
+ 8. Q-Q Plot to Compare Two Datasets
344
+ 9. Scatter Plot Using Sample Data
345
+ [Power BI & DAX]
346
+ 10. Power BI Sales Data Visualization
347
+ 11. Power BI Sales Calculations and DAX Measures
348
+ 12. Power BI Conditional and Logical Analysis (IF, AND, OR)
349
+
350
+ Repository: https://github.com/AnandChowdari/dva-lab.git
351
+ Authoritative Reference: DVA Lab Record
352
+ ================================================================================
353
+ """
354
+ if is_jupyter():
355
+ try:
356
+ from IPython.display import display, Markdown
357
+ display(Markdown(f"```text{text}```"))
358
+ return
359
+ except Exception:
360
+ pass
361
+ print(text)
362
+
363
+
364
+ help = about
@@ -0,0 +1,11 @@
1
+ OrderID,OrderDate,Region,Category,Product,Quantity,UnitPrice,UnitCost,Sales
2
+ 1,2024-01-05,East,Electronics,Laptop,5,800,600,4000
3
+ 2,2024-01-12,West,Electronics,Phone,10,400,300,4000
4
+ 3,2024-02-03,North,Furniture,Chair,20,100,70,2000
5
+ 4,2024-02-15,South,Furniture,Desk,4,300,200,1200
6
+ 5,2024-03-07,East,Electronics,Tablet,12,350,250,4200
7
+ 6,2024-03-21,West,Furniture,Chair,15,100,70,1500
8
+ 7,2024-04-02,North,Electronics,Laptop,3,800,600,2400
9
+ 8,2024-04-18,South,Electronics,Phone,8,400,300,3200
10
+ 9,2024-05-09,East,Furniture,Desk,6,300,200,1800
11
+ 10,2024-05-25,West,Electronics,Laptop,7,800,600,5600
@@ -0,0 +1,53 @@
1
+ """Experiments package for DVA Lab."""
2
+
3
+ from typing import Dict
4
+ from .base import Experiment
5
+ from . import exp01_olap
6
+ from . import exp02_star_schema
7
+ from . import exp03_bar_charts
8
+ from . import exp04_grouped_stacked
9
+ from . import exp05_histograms
10
+ from . import exp06_density
11
+ from . import exp07_ecdf
12
+ from . import exp08_qq_plot
13
+ from . import exp09_scatter
14
+ from . import exp10_powerbi_visualization
15
+ from . import exp11_powerbi_dax
16
+ from . import exp12_powerbi_logic
17
+
18
+ MODULES = [
19
+ exp01_olap,
20
+ exp02_star_schema,
21
+ exp03_bar_charts,
22
+ exp04_grouped_stacked,
23
+ exp05_histograms,
24
+ exp06_density,
25
+ exp07_ecdf,
26
+ exp08_qq_plot,
27
+ exp09_scatter,
28
+ exp10_powerbi_visualization,
29
+ exp11_powerbi_dax,
30
+ exp12_powerbi_logic,
31
+ ]
32
+
33
+ EXPERIMENTS: Dict[int, Experiment] = {
34
+ mod.NUMBER: mod.get_experiment() for mod in MODULES
35
+ }
36
+
37
+ __all__ = [
38
+ "Experiment",
39
+ "EXPERIMENTS",
40
+ "MODULES",
41
+ "exp01_olap",
42
+ "exp02_star_schema",
43
+ "exp03_bar_charts",
44
+ "exp04_grouped_stacked",
45
+ "exp05_histograms",
46
+ "exp06_density",
47
+ "exp07_ecdf",
48
+ "exp08_qq_plot",
49
+ "exp09_scatter",
50
+ "exp10_powerbi_visualization",
51
+ "exp11_powerbi_dax",
52
+ "exp12_powerbi_logic",
53
+ ]
@@ -0,0 +1,43 @@
1
+ """Base data structures and interfaces for DVA Lab experiments."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Callable, List, Optional, Any, Dict
5
+
6
+
7
+ @dataclass
8
+ class Experiment:
9
+ """Represents a DVA laboratory experiment with all metadata and executable logic."""
10
+
11
+ number: int
12
+ title: str
13
+ category: str
14
+ aim: str
15
+ concept: str
16
+ code: str
17
+ dependencies: List[str] = field(default_factory=list)
18
+ expected_output: str = ""
19
+ result: str = ""
20
+ notes: str = ""
21
+ run_func: Optional[Callable[..., Any]] = None
22
+
23
+ def run(self, **kwargs) -> Any:
24
+ """Execute the experiment or display execution instructions."""
25
+ if self.run_func is not None:
26
+ return self.run_func(**kwargs)
27
+ raise NotImplementedError(
28
+ f"Execution logic is not defined for Experiment {self.number}: {self.title}"
29
+ )
30
+
31
+ def to_dict(self) -> Dict[str, Any]:
32
+ """Convert experiment metadata to a dictionary."""
33
+ return {
34
+ "number": self.number,
35
+ "title": self.title,
36
+ "category": self.category,
37
+ "aim": self.aim,
38
+ "concept": self.concept,
39
+ "dependencies": self.dependencies,
40
+ "expected_output": self.expected_output,
41
+ "result": self.result,
42
+ "notes": self.notes,
43
+ }