majoplot 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.
majoplot/__init__.py ADDED
File without changes
majoplot/__main__.py ADDED
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+
5
+ from .app.cli import run_cli
6
+ from .app.gui import run_gui
7
+
8
+
9
+ def main(argv: list[str] | None = None) -> None:
10
+ parser = argparse.ArgumentParser(prog="majoplot")
11
+ group = parser.add_mutually_exclusive_group()
12
+ group.add_argument("--gui", "-g", action="store_true", help="Launch GUI (default)")
13
+ group.add_argument("--cli", "-c", action="store_true", help="Launch CLI")
14
+ args, _ = parser.parse_known_args(argv)
15
+
16
+ if args.cli:
17
+ run_cli()
18
+ return
19
+
20
+ # default GUI (also for --gui/-g)
21
+ run_gui()
22
+
23
+
24
+ if __name__ == "__main__":
25
+ main()
File without changes
majoplot/app/cli.py ADDED
@@ -0,0 +1,259 @@
1
+ from __future__ import annotations
2
+ from pathlib import Path
3
+ import tkinter as tk
4
+ from tkinter import filedialog
5
+ import importlib
6
+ import pkgutil
7
+ from types import ModuleType
8
+ from typing import Any
9
+
10
+ from ..domain.base import *
11
+ from ..domain.utils import group_into_axes, group_into_figure, pack_into_project
12
+ from ..infra.plotters.origin import OriginCOM
13
+ from ..infra.plotters.origin import plot as oplot
14
+
15
+ def load_named_objects(package: str) -> dict[str, Any]:
16
+ """
17
+ Import all submodules under `package`, and extract the attribute
18
+ that has the same name as the module.
19
+
20
+ Example:
21
+ domain.importers.csv -> object named `csv`
22
+ """
23
+ result: dict[str, Any] = {}
24
+
25
+ pkg = importlib.import_module(package)
26
+
27
+ if not hasattr(pkg, "__path__"):
28
+ raise ValueError(f"{package!r} is not a package")
29
+
30
+ for module_info in pkgutil.iter_modules(pkg.__path__):
31
+ module_name = module_info.name
32
+ full_name = f"{package}.{module_name}"
33
+
34
+ module = importlib.import_module(full_name)
35
+
36
+ if hasattr(module, module_name):
37
+ result[module_name] = getattr(module, module_name)
38
+ else:
39
+ raise AttributeError(
40
+ f"Module {full_name} does not define `{module_name}`"
41
+ )
42
+
43
+ return result
44
+
45
+
46
+
47
+
48
+ def pick_multiple_files(
49
+ *,
50
+ title: str = "Select files",
51
+ initial_dir: str | Path | None = None,
52
+ filetypes: list[tuple[str, str]] | None = None,
53
+ ) -> list[Path]:
54
+ root = tk.Tk()
55
+ root.withdraw()
56
+ root.attributes("-topmost", True)
57
+
58
+ try:
59
+ filenames = filedialog.askopenfilenames(
60
+ title=title,
61
+ initialdir=str(Path(initial_dir).resolve()) if initial_dir else None,
62
+ filetypes=filetypes or [("All files", "*.*")],
63
+ )
64
+ return [Path(x).resolve() for x in filenames] # empty list if cancelled
65
+ finally:
66
+ root.destroy()
67
+
68
+ def pick_directory(
69
+ *,
70
+ title: str = "Select directory",
71
+ initial_dir: str | Path | None = None,
72
+ ) -> Path | None:
73
+ root = tk.Tk()
74
+ root.withdraw()
75
+ root.attributes("-topmost", True)
76
+
77
+ try:
78
+ dirname = filedialog.askdirectory(
79
+ title=title,
80
+ initialdir=str(Path(initial_dir).resolve()) if initial_dir else None,
81
+ mustexist=True,
82
+ )
83
+ if not dirname:
84
+ return None # user cancelled
85
+ return Path(dirname).resolve()
86
+ finally:
87
+ root.destroy()
88
+
89
+ def run_cli():
90
+ """
91
+ cli is just for test in early and middle development stage
92
+ """
93
+ print("################")
94
+ print("# MAJOPLOT CLI #")
95
+ print("################")
96
+ importers = load_named_objects("majoplot.domain.importers")
97
+ figures = []
98
+ print("======== Step 1 ========")
99
+ while True:
100
+ print("[Majo]: Now we try to import some raw datas.")
101
+ while True:
102
+ print("[Majo]: Please choose one Importer:")
103
+ print("\n".join(f"\t- {importer}" for importer in importers))
104
+ try:
105
+ chosed_importer_name = input("[You]:").strip()
106
+ chosed_importer = importers[chosed_importer_name]
107
+ except KeyError:
108
+ print(f"[Majo]: Importer '{chosed_importer_name}' not founded. Please try another.")
109
+ continue
110
+ break
111
+ scenarios = load_named_objects(f"majoplot.domain.scenarios.{chosed_importer_name}")
112
+ while True:
113
+ print("[Majo]: Please choose one Scenario:")
114
+ print("\n".join(f"\t- {scenario}" for scenario in scenarios))
115
+ try:
116
+ chosed_scenario_name = input("[You]:").strip()
117
+ chosed_scenario = scenarios[chosed_scenario_name]
118
+ except KeyError:
119
+ print(f"[Majo]: Scenario '{chosed_scenario_name}' not founded. Please try another.")
120
+ continue
121
+ break
122
+
123
+ print("[Majo]: Please choose some raw data files.")
124
+ raw_data_paths = pick_multiple_files(title="Select Raw data files", initial_dir=".")
125
+ print(f"[You]:")
126
+ print("\n".join(f"\t+ {raw_data_path}" for raw_data_path in raw_data_paths))
127
+
128
+
129
+ # make figures
130
+ raw_datas = []
131
+ for path in raw_data_paths:
132
+ with open(path, encoding="utf-8") as fp:
133
+ raw_data = chosed_importer.fetch_raw_data(fp, path.stem)
134
+ if raw_data is not fail_signal:
135
+ raw_datas.append(raw_data)
136
+ datas = chosed_scenario.preprocess(raw_datas)
137
+
138
+
139
+ axes_pool = group_into_axes(datas, chosed_scenario)
140
+ figures.extend(group_into_figure(axes_pool, chosed_scenario))
141
+
142
+
143
+ print("[Majo]: Ok. Shall we proceed to the next step?")
144
+ print("\t- (Y) Yes.")
145
+ print("\t- (N) No, I want to import more datas.")
146
+ choice = input("[You]:")
147
+ if choice.upper() == "Y":
148
+ break
149
+
150
+ print("======== Step 2 ========")
151
+ while True:
152
+ print("[Majo]: We got these figures:")
153
+ print("\n".join(f"\t ({i}) {figure.spec.name}" for i,figure in enumerate(figures)))
154
+ print("[Majo]: You can choose one figure to manipulate. Or you can input:")
155
+ print("\t- (Y) to get to the next step.")
156
+ print("\t- (W) to write and apply a project_name:folder_path pair to all the figures")
157
+ print("\t- (O) to overwrite and apply a project_name:folder_path pair to all the figures")
158
+
159
+ answer = input("[You]:").upper()
160
+ if answer == "Y":
161
+ break
162
+ elif answer == "W" or answer == "O":
163
+ print("[Majo]: Please input a 'proj_name:folder_path' pair. For example: '20260115:MT/LNO'.")
164
+ try:
165
+ pair = input("[You]:").split(":")
166
+ proj_name, folder_path = pair[0:2]
167
+ if answer == "W":
168
+ for figure in figures:
169
+ figure.proj_folder[proj_name] = folder_path
170
+ else:
171
+ for figure in figures:
172
+ figure.proj_folder = {}
173
+ figure.proj_folder[proj_name] = folder_path
174
+ print("[Majo]: Project name and folder Paths applied.")
175
+ except ValueError:
176
+ print("[Majo]: Wrong Input.")
177
+ continue
178
+
179
+
180
+ try:
181
+ index = int(answer)
182
+ except ValueError:
183
+ print("[Majo]: Wrong Input.")
184
+ continue
185
+ try:
186
+ chosed_figure = figures[index]
187
+ except IndexError:
188
+ print("[Majo]: You chosed a figure that doesn't exist.")
189
+ continue
190
+
191
+ while True:
192
+ print(f"[Majo]: This figure is chosed: ({index}) {chosed_figure.spec.name}")
193
+ print("[Majo]: What do you want to do now?")
194
+ print("\t- (D) Delete this figure.")
195
+ print("\t- (P) Preview this figure.")
196
+ print("\t- (S) Show current project_name:folder_path pairs.")
197
+ print("\t- (W) to write and apply a project_name:folder_path pair to all the figures")
198
+ print("\t- (O) to overwrite and apply a project_name:folder_path pair to all the figures")
199
+ print("\t- (C) Cancel and come back.")
200
+ choice = input("[You]:")
201
+ match choice.upper():
202
+ case "D":
203
+ del figures[index]
204
+ break
205
+ case "P":
206
+ import matplotlib.pyplot as plt
207
+ from ..infra.plotters.matplot import plot as mplot
208
+ mfigure = mplot(chosed_figure)
209
+ plt.figure(mfigure)
210
+ plt.show()
211
+ case "C":
212
+ break
213
+ case "S":
214
+ print(f"[Majo]: proj_name:folder_path pairs of {chosed_figure.spec.name}:")
215
+ print("\n".join(f"\t- {proj_name}: {folder_path}" for proj_name, folder_path in chosed_figure.proj_folder.items()))
216
+ case "W" | "O":
217
+ print("[Majo]: Please input a 'proj_name:folder_path' pair. For example: '20260115:MT/LNO'.")
218
+ try:
219
+ pair = input("[You]:").split(":")
220
+ proj_name, folder_path = pair[0:2]
221
+ if choice == "W":
222
+ chosed_figure.proj_folder[proj_name] = folder_path
223
+ else:
224
+ chosed_figure.proj_folder = {}
225
+ chosed_figure.proj_folder[proj_name] = folder_path
226
+ print("[Majo]: Project name and folder Paths applied.")
227
+ except ValueError:
228
+ print("[Majo]: Wrong Input.")
229
+
230
+
231
+ print("======== Step 3 ========")
232
+ print("[Majo]: Please pick a directory to save opju")
233
+ proj_dir = pick_directory(title="Select the directory of OPJU", initial_dir=".")
234
+ while True:
235
+ print("[Majo]: [A] Attach or [O] Overwrite?")
236
+ choice = input("[You]:")
237
+ match choice.upper():
238
+ case "A":
239
+ overwrite = False
240
+ break
241
+ case "O":
242
+ overwrite = True
243
+ break
244
+ case _:
245
+ print("[Majo]: Wrong Input.")
246
+
247
+ projs = pack_into_project(figures)
248
+ print("[Majo]: Launching OriginCOM...")
249
+ with OriginCOM(visible=False) as og:
250
+ for proj_name, proj in projs.items():
251
+ print(f"[Majo]: ploting in the project {proj_name}...")
252
+ oplot(proj, proj_name, og, proj_dir=proj_dir,overwrite=overwrite)
253
+ for folder_name, folder in proj.items():
254
+ for figure_name in folder:
255
+ print(f"\tPlotted: Figure {figure_name} in folder {folder_name}.")
256
+ print("[Majo]: Done.")
257
+
258
+
259
+
majoplot/app/gui.py ADDED
@@ -0,0 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+ def run_gui() -> None:
4
+ """Launch the Tkinter-based GUI."""
5
+ from ..gui.main import main
6
+ main()
majoplot/config.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "scenario": {
3
+ "_items": [
4
+ "DIY",
5
+ "MT"
6
+ ],
7
+ "_selected": 0
8
+ },
9
+ "data path": ".",
10
+ "output path": "./outputs/"
11
+ }