scitex 2.16.0__py3-none-any.whl → 2.16.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.
- scitex/_mcp_tools/audio.py +11 -65
- scitex/audio/README.md +40 -12
- scitex/audio/__init__.py +27 -235
- scitex/audio/_audio_check.py +93 -0
- scitex/audio/_mcp/speak_handlers.py +56 -8
- scitex/audio/_speak.py +295 -0
- scitex/audio/mcp_server.py +98 -73
- scitex/social/__init__.py +1 -24
- scitex/writer/README.md +25 -409
- scitex/writer/__init__.py +98 -13
- {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/METADATA +6 -1
- {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/RECORD +15 -62
- scitex/writer/Writer.py +0 -487
- scitex/writer/_clone_writer_project.py +0 -160
- scitex/writer/_compile/__init__.py +0 -41
- scitex/writer/_compile/_compile_async.py +0 -130
- scitex/writer/_compile/_compile_unified.py +0 -148
- scitex/writer/_compile/_parser.py +0 -63
- scitex/writer/_compile/_runner.py +0 -457
- scitex/writer/_compile/_validator.py +0 -46
- scitex/writer/_compile/manuscript.py +0 -110
- scitex/writer/_compile/revision.py +0 -82
- scitex/writer/_compile/supplementary.py +0 -100
- scitex/writer/_dataclasses/__init__.py +0 -44
- scitex/writer/_dataclasses/config/_CONSTANTS.py +0 -46
- scitex/writer/_dataclasses/config/_WriterConfig.py +0 -175
- scitex/writer/_dataclasses/config/__init__.py +0 -9
- scitex/writer/_dataclasses/contents/_ManuscriptContents.py +0 -236
- scitex/writer/_dataclasses/contents/_RevisionContents.py +0 -136
- scitex/writer/_dataclasses/contents/_SupplementaryContents.py +0 -114
- scitex/writer/_dataclasses/contents/__init__.py +0 -9
- scitex/writer/_dataclasses/core/_Document.py +0 -146
- scitex/writer/_dataclasses/core/_DocumentSection.py +0 -546
- scitex/writer/_dataclasses/core/__init__.py +0 -7
- scitex/writer/_dataclasses/results/_CompilationResult.py +0 -165
- scitex/writer/_dataclasses/results/_LaTeXIssue.py +0 -102
- scitex/writer/_dataclasses/results/_SaveSectionsResponse.py +0 -118
- scitex/writer/_dataclasses/results/_SectionReadResponse.py +0 -131
- scitex/writer/_dataclasses/results/__init__.py +0 -11
- scitex/writer/_dataclasses/tree/MINIMUM_FILES.md +0 -121
- scitex/writer/_dataclasses/tree/_ConfigTree.py +0 -86
- scitex/writer/_dataclasses/tree/_ManuscriptTree.py +0 -84
- scitex/writer/_dataclasses/tree/_RevisionTree.py +0 -97
- scitex/writer/_dataclasses/tree/_ScriptsTree.py +0 -118
- scitex/writer/_dataclasses/tree/_SharedTree.py +0 -100
- scitex/writer/_dataclasses/tree/_SupplementaryTree.py +0 -101
- scitex/writer/_dataclasses/tree/__init__.py +0 -23
- scitex/writer/_mcp/__init__.py +0 -4
- scitex/writer/_mcp/handlers.py +0 -32
- scitex/writer/_mcp/tool_schemas.py +0 -33
- scitex/writer/_project/__init__.py +0 -29
- scitex/writer/_project/_create.py +0 -89
- scitex/writer/_project/_trees.py +0 -63
- scitex/writer/_project/_validate.py +0 -61
- scitex/writer/utils/.legacy_git_retry.py +0 -164
- scitex/writer/utils/__init__.py +0 -24
- scitex/writer/utils/_converters.py +0 -635
- scitex/writer/utils/_parse_latex_logs.py +0 -138
- scitex/writer/utils/_parse_script_args.py +0 -156
- scitex/writer/utils/_verify_tree_structure.py +0 -205
- scitex/writer/utils/_watch.py +0 -96
- {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/WHEEL +0 -0
- {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/entry_points.txt +0 -0
- {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-11-08 (ywatanabe)"
|
|
4
|
-
# File: /home/ywatanabe/proj/scitex-code/src/scitex/writer/_compile/supplementary.py
|
|
5
|
-
# ----------------------------------------
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
import os
|
|
8
|
-
|
|
9
|
-
__FILE__ = "./src/scitex/writer/_compile/supplementary.py"
|
|
10
|
-
__DIR__ = os.path.dirname(__FILE__)
|
|
11
|
-
# ----------------------------------------
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
Supplementary materials compilation function.
|
|
15
|
-
|
|
16
|
-
Provides supplementary-specific compilation with options for:
|
|
17
|
-
- Figure inclusion (default)
|
|
18
|
-
- PowerPoint to TIF conversion
|
|
19
|
-
- TIF cropping
|
|
20
|
-
- Quiet mode
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
from pathlib import Path
|
|
24
|
-
from typing import Optional, Callable
|
|
25
|
-
from ._runner import run_compile
|
|
26
|
-
from .._dataclasses import CompilationResult
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def compile_supplementary(
|
|
30
|
-
project_dir: Path,
|
|
31
|
-
timeout: int = 300,
|
|
32
|
-
no_figs: bool = False,
|
|
33
|
-
ppt2tif: bool = False,
|
|
34
|
-
crop_tif: bool = False,
|
|
35
|
-
quiet: bool = False,
|
|
36
|
-
log_callback: Optional[Callable[[str], None]] = None,
|
|
37
|
-
progress_callback: Optional[Callable[[int, str], None]] = None,
|
|
38
|
-
) -> CompilationResult:
|
|
39
|
-
"""
|
|
40
|
-
Compile supplementary materials with optional callbacks.
|
|
41
|
-
|
|
42
|
-
Parameters
|
|
43
|
-
----------
|
|
44
|
-
project_dir : Path
|
|
45
|
-
Path to writer project directory
|
|
46
|
-
timeout : int
|
|
47
|
-
Timeout in seconds
|
|
48
|
-
no_figs : bool
|
|
49
|
-
Exclude figures (default includes figures)
|
|
50
|
-
ppt2tif : bool
|
|
51
|
-
Convert PowerPoint to TIF on WSL
|
|
52
|
-
crop_tif : bool
|
|
53
|
-
Crop TIF images to remove excess whitespace
|
|
54
|
-
quiet : bool
|
|
55
|
-
Suppress detailed logs for LaTeX compilation
|
|
56
|
-
log_callback : Optional[Callable[[str], None]]
|
|
57
|
-
Called with each log line
|
|
58
|
-
progress_callback : Optional[Callable[[int, str], None]]
|
|
59
|
-
Called with progress updates (percent, step)
|
|
60
|
-
|
|
61
|
-
Returns
|
|
62
|
-
-------
|
|
63
|
-
CompilationResult
|
|
64
|
-
Compilation status and outputs
|
|
65
|
-
|
|
66
|
-
Examples
|
|
67
|
-
--------
|
|
68
|
-
>>> from pathlib import Path
|
|
69
|
-
>>> from scitex.writer._compile import compile_supplementary
|
|
70
|
-
>>>
|
|
71
|
-
>>> # Standard compilation with figures
|
|
72
|
-
>>> result = compile_supplementary(
|
|
73
|
-
... project_dir=Path("~/my-paper"),
|
|
74
|
-
... ppt2tif=True,
|
|
75
|
-
... quiet=False
|
|
76
|
-
... )
|
|
77
|
-
>>>
|
|
78
|
-
>>> # Quick compilation without figures
|
|
79
|
-
>>> result = compile_supplementary(
|
|
80
|
-
... project_dir=Path("~/my-paper"),
|
|
81
|
-
... no_figs=True,
|
|
82
|
-
... quiet=True
|
|
83
|
-
... )
|
|
84
|
-
"""
|
|
85
|
-
return run_compile(
|
|
86
|
-
"supplementary",
|
|
87
|
-
project_dir,
|
|
88
|
-
timeout=timeout,
|
|
89
|
-
no_figs=no_figs,
|
|
90
|
-
ppt2tif=ppt2tif,
|
|
91
|
-
crop_tif=crop_tif,
|
|
92
|
-
quiet=quiet,
|
|
93
|
-
log_callback=log_callback,
|
|
94
|
-
progress_callback=progress_callback,
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
__all__ = ["compile_supplementary"]
|
|
99
|
-
|
|
100
|
-
# EOF
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# File: /home/ywatanabe/proj/scitex-code/src/scitex/writer/dataclasses/__init__.py
|
|
4
|
-
|
|
5
|
-
"""
|
|
6
|
-
Type definitions for Writer module.
|
|
7
|
-
|
|
8
|
-
Provides dataclasses for document structures with clear separation of concerns.
|
|
9
|
-
Each document type includes:
|
|
10
|
-
- Typed access to sections and files
|
|
11
|
-
- Nested Contents dataclass for content/ subdirectory
|
|
12
|
-
- verify_structure() method for validation
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
from .core import Document, DocumentSection
|
|
16
|
-
from .contents import ManuscriptContents, SupplementaryContents, RevisionContents
|
|
17
|
-
from .config import WriterConfig
|
|
18
|
-
from .results import CompilationResult, LaTeXIssue
|
|
19
|
-
|
|
20
|
-
# Tree structures (internal use)
|
|
21
|
-
from .tree import (
|
|
22
|
-
ConfigTree,
|
|
23
|
-
SharedTree,
|
|
24
|
-
ScriptsTree,
|
|
25
|
-
ManuscriptTree,
|
|
26
|
-
SupplementaryTree,
|
|
27
|
-
RevisionTree,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
__all__ = [
|
|
31
|
-
# Core document dataclasses
|
|
32
|
-
"DocumentSection",
|
|
33
|
-
"Document",
|
|
34
|
-
# Document contents
|
|
35
|
-
"ManuscriptContents",
|
|
36
|
-
"SupplementaryContents",
|
|
37
|
-
"RevisionContents",
|
|
38
|
-
# Configuration and results
|
|
39
|
-
"CompilationResult",
|
|
40
|
-
"WriterConfig",
|
|
41
|
-
"LaTeXIssue",
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
# EOF
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-10-29 06:08:36 (ywatanabe)"
|
|
4
|
-
# File: /home/ywatanabe/proj/scitex-code/src/scitex/writer/dataclasses/_CONSTANTS.py
|
|
5
|
-
# ----------------------------------------
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
import os
|
|
8
|
-
|
|
9
|
-
__FILE__ = "./src/scitex/writer/dataclasses/_CONSTANTS.py"
|
|
10
|
-
__DIR__ = os.path.dirname(__FILE__)
|
|
11
|
-
# ----------------------------------------
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
Constants for writer module.
|
|
15
|
-
|
|
16
|
-
Centralized definitions for document dataclasses and directory mappings.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
# Document type to directory mapping
|
|
20
|
-
DOC_TYPE_DIRS = {
|
|
21
|
-
"manuscript": "01_manuscript",
|
|
22
|
-
"supplementary": "02_supplementary",
|
|
23
|
-
"revision": "03_revision",
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
# Document type to command-line flag mapping
|
|
27
|
-
DOC_TYPE_FLAGS = {
|
|
28
|
-
"manuscript": "-m",
|
|
29
|
-
"supplementary": "-s",
|
|
30
|
-
"revision": "-r",
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
# Document type to PDF filename mapping
|
|
34
|
-
DOC_TYPE_PDFS = {
|
|
35
|
-
"manuscript": "manuscript.pdf",
|
|
36
|
-
"supplementary": "supplementary.pdf",
|
|
37
|
-
"revision": "revision.pdf",
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
__all__ = [
|
|
41
|
-
"DOC_TYPE_DIRS",
|
|
42
|
-
"DOC_TYPE_FLAGS",
|
|
43
|
-
"DOC_TYPE_PDFS",
|
|
44
|
-
]
|
|
45
|
-
|
|
46
|
-
# EOF
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-10-29 06:08:47 (ywatanabe)"
|
|
4
|
-
# File: /home/ywatanabe/proj/scitex-code/src/scitex/writer/dataclasses/_WriterConfig.py
|
|
5
|
-
# ----------------------------------------
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
import os
|
|
8
|
-
|
|
9
|
-
__FILE__ = "./src/scitex/writer/dataclasses/_WriterConfig.py"
|
|
10
|
-
__DIR__ = os.path.dirname(__FILE__)
|
|
11
|
-
# ----------------------------------------
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
WriterConfig - dataclass for writer configuration.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
from dataclasses import dataclass
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
from typing import Optional
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@dataclass
|
|
23
|
-
class WriterConfig:
|
|
24
|
-
"""Configuration for scitex.writer."""
|
|
25
|
-
|
|
26
|
-
project_dir: Path
|
|
27
|
-
"""Root directory of writer project"""
|
|
28
|
-
|
|
29
|
-
manuscript_dir: Path
|
|
30
|
-
"""Directory for manuscript (01_manuscript/)"""
|
|
31
|
-
|
|
32
|
-
supplementary_dir: Path
|
|
33
|
-
"""Directory for supplementary (02_supplementary/)"""
|
|
34
|
-
|
|
35
|
-
revision_dir: Path
|
|
36
|
-
"""Directory for revision (03_revision/)"""
|
|
37
|
-
|
|
38
|
-
shared_dir: Path
|
|
39
|
-
"""Directory for shared resources (00_shared/)"""
|
|
40
|
-
|
|
41
|
-
compile_script: Optional[Path] = None
|
|
42
|
-
"""Path to compile script (auto-detected if None)"""
|
|
43
|
-
|
|
44
|
-
@classmethod
|
|
45
|
-
def from_directory(cls, project_dir: Path) -> "WriterConfig":
|
|
46
|
-
"""
|
|
47
|
-
Create config from project directory.
|
|
48
|
-
|
|
49
|
-
Args:
|
|
50
|
-
project_dir: Path to writer project root
|
|
51
|
-
|
|
52
|
-
Returns:
|
|
53
|
-
WriterConfig instance
|
|
54
|
-
|
|
55
|
-
Examples:
|
|
56
|
-
>>> config = WriterConfig.from_directory(Path("/path/to/project"))
|
|
57
|
-
>>> print(config.manuscript_dir)
|
|
58
|
-
"""
|
|
59
|
-
project_dir = Path(project_dir)
|
|
60
|
-
|
|
61
|
-
return cls(
|
|
62
|
-
project_dir=project_dir,
|
|
63
|
-
manuscript_dir=project_dir / "01_manuscript",
|
|
64
|
-
supplementary_dir=project_dir / "02_supplementary",
|
|
65
|
-
revision_dir=project_dir / "03_revision",
|
|
66
|
-
shared_dir=project_dir / "00_shared",
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
def validate(self) -> bool:
|
|
70
|
-
"""
|
|
71
|
-
Validate that required directories exist.
|
|
72
|
-
|
|
73
|
-
Returns:
|
|
74
|
-
True if valid writer project structure
|
|
75
|
-
|
|
76
|
-
Raises:
|
|
77
|
-
ValueError: If invalid structure
|
|
78
|
-
"""
|
|
79
|
-
if not self.project_dir.exists():
|
|
80
|
-
raise ValueError(f"Project directory not found: {self.project_dir}")
|
|
81
|
-
|
|
82
|
-
# Check for at least one document directory
|
|
83
|
-
doc_dirs = [
|
|
84
|
-
self.manuscript_dir,
|
|
85
|
-
self.supplementary_dir,
|
|
86
|
-
self.revision_dir,
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
if not any(d.exists() for d in doc_dirs):
|
|
90
|
-
raise ValueError(
|
|
91
|
-
f"No document directories found in {self.project_dir}. "
|
|
92
|
-
"Expected: 01_manuscript/, 02_supplementary/, or 03_revision/"
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
return True
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def run_session() -> None:
|
|
99
|
-
"""Initialize scitex framework, run main function, and cleanup."""
|
|
100
|
-
global CONFIG, CC, sys, plt, rng
|
|
101
|
-
import sys
|
|
102
|
-
import matplotlib.pyplot as plt
|
|
103
|
-
import scitex as stx
|
|
104
|
-
|
|
105
|
-
args = parse_args()
|
|
106
|
-
|
|
107
|
-
CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
|
|
108
|
-
sys,
|
|
109
|
-
plt,
|
|
110
|
-
args=args,
|
|
111
|
-
file=__FILE__,
|
|
112
|
-
sdir_suffix=None,
|
|
113
|
-
verbose=False,
|
|
114
|
-
agg=True,
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
exit_status = main(args)
|
|
118
|
-
|
|
119
|
-
stx.session.close(
|
|
120
|
-
CONFIG,
|
|
121
|
-
verbose=False,
|
|
122
|
-
notify=False,
|
|
123
|
-
message="",
|
|
124
|
-
exit_status=exit_status,
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def main(args):
|
|
129
|
-
config = WriterConfig.from_directory(Path(args.dir))
|
|
130
|
-
|
|
131
|
-
print(f"Project dir: {config.project_dir}")
|
|
132
|
-
print(f"Manuscript dir: {config.manuscript_dir}")
|
|
133
|
-
print(f"Supplementary dir: {config.supplementary_dir}")
|
|
134
|
-
print(f"Revision dir: {config.revision_dir}")
|
|
135
|
-
print(f"Shared dir: {config.shared_dir}")
|
|
136
|
-
|
|
137
|
-
if args.validate:
|
|
138
|
-
try:
|
|
139
|
-
config.validate()
|
|
140
|
-
print("\nValidation: PASSED")
|
|
141
|
-
except ValueError as ee:
|
|
142
|
-
print(f"\nValidation: FAILED - {ee}")
|
|
143
|
-
return 1
|
|
144
|
-
|
|
145
|
-
return 0
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
def parse_args():
|
|
149
|
-
import argparse
|
|
150
|
-
|
|
151
|
-
parser = argparse.ArgumentParser(description="Demonstrate WriterConfig dataclass")
|
|
152
|
-
parser.add_argument(
|
|
153
|
-
"--dir",
|
|
154
|
-
type=str,
|
|
155
|
-
default="./my_paper",
|
|
156
|
-
help="Project directory (default: ./my_paper)",
|
|
157
|
-
)
|
|
158
|
-
parser.add_argument(
|
|
159
|
-
"--validate",
|
|
160
|
-
action="store_true",
|
|
161
|
-
help="Validate directory structure",
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
return parser.parse_args()
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if __name__ == "__main__":
|
|
168
|
-
run_session()
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
__all__ = ["WriterConfig"]
|
|
172
|
-
|
|
173
|
-
# python -m scitex.writer._dataclasses.config._WriterConfig --dir ./my_paper --validate
|
|
174
|
-
|
|
175
|
-
# EOF
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-10-29 06:08:43 (ywatanabe)"
|
|
4
|
-
# File: /home/ywatanabe/proj/scitex-code/src/scitex/writer/dataclasses/_ManuscriptContents.py
|
|
5
|
-
# ----------------------------------------
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
import os
|
|
8
|
-
|
|
9
|
-
__FILE__ = "./src/scitex/writer/dataclasses/_ManuscriptContents.py"
|
|
10
|
-
__DIR__ = os.path.dirname(__FILE__)
|
|
11
|
-
# ----------------------------------------
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
ManuscriptContents - dataclass for manuscript contents structure.
|
|
15
|
-
|
|
16
|
-
Represents the 01_manuscript/contents/ directory structure with all files.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
from typing import Optional
|
|
21
|
-
from dataclasses import dataclass
|
|
22
|
-
|
|
23
|
-
from ..core import DocumentSection
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@dataclass
|
|
27
|
-
class ManuscriptContents:
|
|
28
|
-
"""Contents subdirectory of manuscript (01_manuscript/contents/)."""
|
|
29
|
-
|
|
30
|
-
root: Path
|
|
31
|
-
git_root: Optional[Path] = None
|
|
32
|
-
|
|
33
|
-
# Core sections
|
|
34
|
-
abstract: DocumentSection = None
|
|
35
|
-
introduction: DocumentSection = None
|
|
36
|
-
methods: DocumentSection = None
|
|
37
|
-
results: DocumentSection = None
|
|
38
|
-
discussion: DocumentSection = None
|
|
39
|
-
|
|
40
|
-
# Metadata
|
|
41
|
-
title: DocumentSection = None
|
|
42
|
-
authors: DocumentSection = None
|
|
43
|
-
keywords: DocumentSection = None
|
|
44
|
-
journal_name: DocumentSection = None
|
|
45
|
-
|
|
46
|
-
# Optional sections
|
|
47
|
-
graphical_abstract: DocumentSection = None
|
|
48
|
-
highlights: DocumentSection = None
|
|
49
|
-
data_availability: DocumentSection = None
|
|
50
|
-
additional_info: DocumentSection = None
|
|
51
|
-
wordcount: DocumentSection = None
|
|
52
|
-
|
|
53
|
-
# Files/directories
|
|
54
|
-
figures: Path = None
|
|
55
|
-
tables: Path = None
|
|
56
|
-
bibliography: DocumentSection = None
|
|
57
|
-
latex_styles: Path = None
|
|
58
|
-
|
|
59
|
-
def __post_init__(self):
|
|
60
|
-
"""Initialize all DocumentSection instances."""
|
|
61
|
-
if self.abstract is None:
|
|
62
|
-
self.abstract = DocumentSection(self.root / "abstract.tex", self.git_root)
|
|
63
|
-
if self.introduction is None:
|
|
64
|
-
self.introduction = DocumentSection(
|
|
65
|
-
self.root / "introduction.tex", self.git_root
|
|
66
|
-
)
|
|
67
|
-
if self.methods is None:
|
|
68
|
-
self.methods = DocumentSection(self.root / "methods.tex", self.git_root)
|
|
69
|
-
if self.results is None:
|
|
70
|
-
self.results = DocumentSection(self.root / "results.tex", self.git_root)
|
|
71
|
-
if self.discussion is None:
|
|
72
|
-
self.discussion = DocumentSection(
|
|
73
|
-
self.root / "discussion.tex", self.git_root
|
|
74
|
-
)
|
|
75
|
-
if self.title is None:
|
|
76
|
-
self.title = DocumentSection(self.root / "title.tex", self.git_root)
|
|
77
|
-
if self.authors is None:
|
|
78
|
-
self.authors = DocumentSection(self.root / "authors.tex", self.git_root)
|
|
79
|
-
if self.keywords is None:
|
|
80
|
-
self.keywords = DocumentSection(self.root / "keywords.tex", self.git_root)
|
|
81
|
-
if self.journal_name is None:
|
|
82
|
-
self.journal_name = DocumentSection(
|
|
83
|
-
self.root / "journal_name.tex", self.git_root
|
|
84
|
-
)
|
|
85
|
-
if self.graphical_abstract is None:
|
|
86
|
-
self.graphical_abstract = DocumentSection(
|
|
87
|
-
self.root / "graphical_abstract.tex", self.git_root
|
|
88
|
-
)
|
|
89
|
-
if self.highlights is None:
|
|
90
|
-
self.highlights = DocumentSection(
|
|
91
|
-
self.root / "highlights.tex", self.git_root
|
|
92
|
-
)
|
|
93
|
-
if self.data_availability is None:
|
|
94
|
-
self.data_availability = DocumentSection(
|
|
95
|
-
self.root / "data_availability.tex", self.git_root
|
|
96
|
-
)
|
|
97
|
-
if self.additional_info is None:
|
|
98
|
-
self.additional_info = DocumentSection(
|
|
99
|
-
self.root / "additional_info.tex", self.git_root
|
|
100
|
-
)
|
|
101
|
-
if self.wordcount is None:
|
|
102
|
-
self.wordcount = DocumentSection(self.root / "wordcount.tex", self.git_root)
|
|
103
|
-
if self.figures is None:
|
|
104
|
-
self.figures = self.root / "figures"
|
|
105
|
-
if self.tables is None:
|
|
106
|
-
self.tables = self.root / "tables"
|
|
107
|
-
if self.bibliography is None:
|
|
108
|
-
self.bibliography = DocumentSection(
|
|
109
|
-
self.root / "bibliography.bib", self.git_root
|
|
110
|
-
)
|
|
111
|
-
if self.latex_styles is None:
|
|
112
|
-
self.latex_styles = self.root / "latex_styles"
|
|
113
|
-
|
|
114
|
-
def verify_structure(self) -> tuple[bool, list[str]]:
|
|
115
|
-
"""
|
|
116
|
-
Verify manuscript structure has required files.
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
(is_valid, list_of_missing_files_with_paths)
|
|
120
|
-
"""
|
|
121
|
-
required = [
|
|
122
|
-
("abstract.tex", self.abstract),
|
|
123
|
-
("introduction.tex", self.introduction),
|
|
124
|
-
("methods.tex", self.methods),
|
|
125
|
-
("results.tex", self.results),
|
|
126
|
-
("discussion.tex", self.discussion),
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
missing = []
|
|
130
|
-
for name, section in required:
|
|
131
|
-
if not section.path.exists():
|
|
132
|
-
expected_path = (
|
|
133
|
-
section.path.relative_to(self.git_root)
|
|
134
|
-
if self.git_root
|
|
135
|
-
else section.path
|
|
136
|
-
)
|
|
137
|
-
missing.append(f"{name} (expected at: {expected_path})")
|
|
138
|
-
|
|
139
|
-
return len(missing) == 0, missing
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def run_session() -> None:
|
|
143
|
-
"""Initialize scitex framework, run main function, and cleanup."""
|
|
144
|
-
global CONFIG, CC, sys, plt, rng
|
|
145
|
-
import sys
|
|
146
|
-
import matplotlib.pyplot as plt
|
|
147
|
-
import scitex as stx
|
|
148
|
-
|
|
149
|
-
args = parse_args()
|
|
150
|
-
|
|
151
|
-
CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
|
|
152
|
-
sys,
|
|
153
|
-
plt,
|
|
154
|
-
args=args,
|
|
155
|
-
file=__FILE__,
|
|
156
|
-
sdir_suffix=None,
|
|
157
|
-
verbose=False,
|
|
158
|
-
agg=True,
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
exit_status = main(args)
|
|
162
|
-
|
|
163
|
-
stx.session.close(
|
|
164
|
-
CONFIG,
|
|
165
|
-
verbose=False,
|
|
166
|
-
notify=False,
|
|
167
|
-
message="",
|
|
168
|
-
exit_status=exit_status,
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
def main(args):
|
|
173
|
-
contents_path = Path(args.dir) / "01_manuscript" / "contents"
|
|
174
|
-
git_root = Path(args.dir) if args.git_root else None
|
|
175
|
-
|
|
176
|
-
contents = ManuscriptContents(
|
|
177
|
-
root=contents_path,
|
|
178
|
-
git_root=git_root,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
print(f"Root: {contents.root}")
|
|
182
|
-
print(f"Git root: {contents.git_root}")
|
|
183
|
-
print(f"\nCore sections:")
|
|
184
|
-
print(f" Abstract: {contents.abstract.path}")
|
|
185
|
-
print(f" Introduction: {contents.introduction.path}")
|
|
186
|
-
print(f" Methods: {contents.methods.path}")
|
|
187
|
-
print(f" Results: {contents.results.path}")
|
|
188
|
-
print(f" Discussion: {contents.discussion.path}")
|
|
189
|
-
|
|
190
|
-
if args.verify:
|
|
191
|
-
is_valid, missing = contents.verify_structure()
|
|
192
|
-
if is_valid:
|
|
193
|
-
print("\nStructure verification: PASSED")
|
|
194
|
-
else:
|
|
195
|
-
print(f"\nStructure verification: FAILED")
|
|
196
|
-
print(f"Missing files: {', '.join(missing)}")
|
|
197
|
-
return 1
|
|
198
|
-
|
|
199
|
-
return 0
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def parse_args():
|
|
203
|
-
import argparse
|
|
204
|
-
|
|
205
|
-
parser = argparse.ArgumentParser(
|
|
206
|
-
description="Demonstrate ManuscriptContents dataclass"
|
|
207
|
-
)
|
|
208
|
-
parser.add_argument(
|
|
209
|
-
"--dir",
|
|
210
|
-
type=str,
|
|
211
|
-
default="./my_paper",
|
|
212
|
-
help="Project directory (default: ./my_paper)",
|
|
213
|
-
)
|
|
214
|
-
parser.add_argument(
|
|
215
|
-
"--git-root",
|
|
216
|
-
action="store_true",
|
|
217
|
-
help="Use project dir as git root",
|
|
218
|
-
)
|
|
219
|
-
parser.add_argument(
|
|
220
|
-
"--verify",
|
|
221
|
-
action="store_true",
|
|
222
|
-
help="Verify structure has required files",
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
return parser.parse_args()
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if __name__ == "__main__":
|
|
229
|
-
run_session()
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
__all__ = ["ManuscriptContents"]
|
|
233
|
-
|
|
234
|
-
# python -m scitex.writer._dataclasses.contents._ManuscriptContents --dir ./my_paper --verify
|
|
235
|
-
|
|
236
|
-
# EOF
|