masster 0.5.16__py3-none-any.whl → 0.5.17__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.
Potentially problematic release.
This version of masster might be problematic. Click here for more details.
- masster/_version.py +1 -1
- masster/wizard/wizard.py +178 -225
- {masster-0.5.16.dist-info → masster-0.5.17.dist-info}/METADATA +1 -3
- {masster-0.5.16.dist-info → masster-0.5.17.dist-info}/RECORD +7 -7
- {masster-0.5.16.dist-info → masster-0.5.17.dist-info}/WHEEL +0 -0
- {masster-0.5.16.dist-info → masster-0.5.17.dist-info}/entry_points.txt +0 -0
- {masster-0.5.16.dist-info → masster-0.5.17.dist-info}/licenses/LICENSE +0 -0
masster/_version.py
CHANGED
masster/wizard/wizard.py
CHANGED
|
@@ -228,9 +228,17 @@ class Wizard:
|
|
|
228
228
|
that process raw MS data through the complete pipeline: file discovery, feature
|
|
229
229
|
detection, sample processing, study assembly, alignment, merging, and export.
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
Core functions:
|
|
232
232
|
- create_scripts(): Generate standalone analysis scripts
|
|
233
|
-
-
|
|
233
|
+
- test_only(): Process only one file for parameter validation
|
|
234
|
+
- test_and_run(): Test with single file, then run full batch if successful
|
|
235
|
+
- run(): Execute full batch processing on all files
|
|
236
|
+
|
|
237
|
+
Recommended workflow:
|
|
238
|
+
1. wizard = Wizard(source="raw_data", folder="output")
|
|
239
|
+
2. wizard.create_scripts() # Generate analysis scripts
|
|
240
|
+
3. wizard.test_only() # Validate with single file
|
|
241
|
+
4. wizard.run() # Process all files
|
|
234
242
|
"""
|
|
235
243
|
|
|
236
244
|
def __init__(
|
|
@@ -381,6 +389,9 @@ class Wizard:
|
|
|
381
389
|
workflow_script_path = self.folder_path / "1_masster_workflow.py"
|
|
382
390
|
workflow_content = self._generate_workflow_script_content(source_info)
|
|
383
391
|
|
|
392
|
+
# Apply test mode modifications
|
|
393
|
+
workflow_content = self._add_test_mode_support(workflow_content)
|
|
394
|
+
|
|
384
395
|
with open(workflow_script_path, 'w', encoding='utf-8') as f:
|
|
385
396
|
f.write(workflow_content)
|
|
386
397
|
files_created.append(str(workflow_script_path))
|
|
@@ -458,6 +469,7 @@ class Wizard:
|
|
|
458
469
|
'Generated by masster wizard',
|
|
459
470
|
'"""',
|
|
460
471
|
'',
|
|
472
|
+
'import os',
|
|
461
473
|
'import sys',
|
|
462
474
|
'import time',
|
|
463
475
|
'from pathlib import Path',
|
|
@@ -466,6 +478,10 @@ class Wizard:
|
|
|
466
478
|
'from masster.study import Study',
|
|
467
479
|
'from masster import __version__',
|
|
468
480
|
'',
|
|
481
|
+
'# Test mode configuration',
|
|
482
|
+
'TEST_MODE = os.environ.get("MASSTER_TEST_MODE", "0") == "1"',
|
|
483
|
+
'TEST_ONLY = os.environ.get("MASSTER_TEST_ONLY", "0") == "1" # Only run test, don\'t continue to full batch',
|
|
484
|
+
'',
|
|
469
485
|
'# Analysis parameters',
|
|
470
486
|
'PARAMS = {',
|
|
471
487
|
' # === Core Configuration ===',
|
|
@@ -474,6 +490,10 @@ class Wizard:
|
|
|
474
490
|
f' "polarity": {self.params.polarity!r}, # Ion polarity mode ("positive" or "negative")',
|
|
475
491
|
f' "num_cores": {self.params.num_cores}, # Number of CPU cores for parallel processing',
|
|
476
492
|
'',
|
|
493
|
+
' # === Test Mode ===',
|
|
494
|
+
' "test_mode": TEST_MODE, # Process only first file for testing',
|
|
495
|
+
' "test_only": TEST_ONLY, # Stop after test, don\'t run full batch',
|
|
496
|
+
'',
|
|
477
497
|
' # === File Discovery ===',
|
|
478
498
|
f' "file_extensions": {self.params.file_extensions!r}, # File extensions to search for',
|
|
479
499
|
f' "search_subfolders": {self.params.search_subfolders}, # Whether to search subdirectories recursively',
|
|
@@ -779,71 +799,198 @@ class Wizard:
|
|
|
779
799
|
f"1. REVIEW PARAMETERS in {workflow_script_name}:",
|
|
780
800
|
f" In particular, verify the NOISE, CHROM_FWHM, and MIN_SAMPLES_FOR_MERGE",
|
|
781
801
|
"",
|
|
782
|
-
"2.
|
|
783
|
-
f"
|
|
802
|
+
"2. TEST SINGLE FILE (RECOMMENDED):",
|
|
803
|
+
f" wizard.test_only() # Validate parameters with first file only",
|
|
804
|
+
"",
|
|
805
|
+
"3. EXECUTE FULL BATCH:",
|
|
806
|
+
f" wizard.run() # Process all files",
|
|
807
|
+
f" # OR: wizard.test_and_run() # Test first, then run all",
|
|
808
|
+
f" # OR: uv run python {workflow_script_name}",
|
|
784
809
|
"",
|
|
785
|
-
"
|
|
810
|
+
"4. INTERACTIVE ANALYSIS:",
|
|
786
811
|
f" uv run marimo edit {Path('2_interactive_analysis.py').name}",
|
|
787
812
|
""]
|
|
788
813
|
)
|
|
789
814
|
|
|
790
815
|
return instructions
|
|
791
816
|
|
|
792
|
-
def
|
|
817
|
+
def _add_test_mode_support(self, workflow_content: str) -> str:
|
|
818
|
+
"""Add test mode functionality to the generated workflow script."""
|
|
819
|
+
lines = workflow_content.split('\n')
|
|
820
|
+
|
|
821
|
+
# Insert test mode code after print statements in main function
|
|
822
|
+
for i, line in enumerate(lines):
|
|
823
|
+
# Add test mode print after the masster version line
|
|
824
|
+
if 'print("masster' in line and 'Automated MS Data Analysis")' in line:
|
|
825
|
+
lines.insert(i + 1, ' if TEST_MODE:')
|
|
826
|
+
lines.insert(i + 2, ' print("🧪 TEST MODE: Processing single file only")')
|
|
827
|
+
break
|
|
828
|
+
|
|
829
|
+
# Add mode info after num_cores print
|
|
830
|
+
for i, line in enumerate(lines):
|
|
831
|
+
if 'print(f"CPU Cores: {PARAMS[\'num_cores\']}")' in line:
|
|
832
|
+
lines.insert(i + 1, ' if TEST_MODE:')
|
|
833
|
+
lines.insert(i + 2, ' print(f"Mode: {\'Test Only\' if TEST_ONLY else \'Test + Full Batch\'}")')
|
|
834
|
+
break
|
|
835
|
+
|
|
836
|
+
# Add file limitation logic after file listing
|
|
837
|
+
for i, line in enumerate(lines):
|
|
838
|
+
if 'print(f" ... and {len(raw_files) - 5} more")' in line:
|
|
839
|
+
lines.insert(i + 1, ' ')
|
|
840
|
+
lines.insert(i + 2, ' # Limit to first file in test mode')
|
|
841
|
+
lines.insert(i + 3, ' if TEST_MODE:')
|
|
842
|
+
lines.insert(i + 4, ' raw_files = raw_files[:1]')
|
|
843
|
+
lines.insert(i + 5, ' print(f"\\n🧪 TEST MODE: Processing only first file: {raw_files[0].name}")')
|
|
844
|
+
break
|
|
845
|
+
|
|
846
|
+
# Modify num_cores for test mode
|
|
847
|
+
for i, line in enumerate(lines):
|
|
848
|
+
if 'PARAMS[\'num_cores\']' in line and 'convert_raw_to_sample5(' in lines[i-2:i+3]:
|
|
849
|
+
lines[i] = line.replace('PARAMS[\'num_cores\']', 'PARAMS[\'num_cores\'] if not TEST_MODE else 1 # Use single core for test')
|
|
850
|
+
break
|
|
851
|
+
|
|
852
|
+
# Add test-only exit logic after successful processing
|
|
853
|
+
for i, line in enumerate(lines):
|
|
854
|
+
if 'print(f"Successfully processed {len(sample5_files)} files to sample5")' in line:
|
|
855
|
+
lines.insert(i + 1, ' ')
|
|
856
|
+
lines.insert(i + 2, ' # Stop here if test-only mode')
|
|
857
|
+
lines.insert(i + 3, ' if TEST_ONLY:')
|
|
858
|
+
lines.insert(i + 4, ' print("\\n🧪 TEST ONLY mode: Stopping after successful single file processing")')
|
|
859
|
+
lines.insert(i + 5, ' print(f"Test file created: {sample5_files[0]}")')
|
|
860
|
+
lines.insert(i + 6, ' print("\\nTo run full batch, use: wizard.run()")')
|
|
861
|
+
lines.insert(i + 7, ' total_time = time.time() - start_time')
|
|
862
|
+
lines.insert(i + 8, ' print(f"\\nTest processing time: {total_time:.1f} seconds")')
|
|
863
|
+
lines.insert(i + 9, ' return True')
|
|
864
|
+
break
|
|
865
|
+
|
|
866
|
+
return '\n'.join(lines)
|
|
867
|
+
|
|
868
|
+
def test_and_run(self) -> Dict[str, Any]:
|
|
793
869
|
"""
|
|
794
|
-
|
|
870
|
+
Test the sample processing workflow with a single file, then run full batch.
|
|
795
871
|
|
|
796
|
-
This method
|
|
797
|
-
|
|
798
|
-
|
|
872
|
+
This method runs the 1_masster_workflow.py script in test mode to process
|
|
873
|
+
the first raw file for validation, then automatically continues with the
|
|
874
|
+
full batch if the test succeeds. The script must already exist - call
|
|
875
|
+
create_scripts() first if needed.
|
|
799
876
|
|
|
800
877
|
Returns:
|
|
801
878
|
Dictionary containing:
|
|
802
|
-
- status: "success"
|
|
879
|
+
- status: "success" or "error"
|
|
803
880
|
- message: Status message
|
|
804
881
|
- instructions: List of next steps
|
|
805
|
-
|
|
882
|
+
"""
|
|
883
|
+
return self._execute_workflow(test_mode=True)
|
|
884
|
+
|
|
885
|
+
def test_only(self) -> Dict[str, Any]:
|
|
886
|
+
"""
|
|
887
|
+
Test the sample processing workflow with a single file only.
|
|
888
|
+
|
|
889
|
+
This method runs the 1_masster_workflow.py script in test-only mode to process
|
|
890
|
+
only the first raw file and then stops (does not continue to full study processing).
|
|
891
|
+
The script must already exist - call create_scripts() first if needed.
|
|
892
|
+
|
|
893
|
+
Returns:
|
|
894
|
+
Dictionary containing:
|
|
895
|
+
- status: "success" or "error"
|
|
896
|
+
- message: Status message
|
|
897
|
+
- instructions: List of next steps
|
|
898
|
+
- test_file: Path to the processed test file (if successful)
|
|
899
|
+
"""
|
|
900
|
+
return self._execute_workflow(test_mode=True, test_only=True)
|
|
901
|
+
|
|
902
|
+
def run(self) -> Dict[str, Any]:
|
|
903
|
+
"""
|
|
904
|
+
Run the sample processing workflow.
|
|
905
|
+
|
|
906
|
+
This method runs the 1_masster_workflow.py script to process raw files.
|
|
907
|
+
The script must already exist - call create_scripts() first if needed.
|
|
908
|
+
|
|
909
|
+
Returns:
|
|
910
|
+
Dictionary containing:
|
|
911
|
+
- status: "success" or "error"
|
|
912
|
+
- message: Status message
|
|
913
|
+
- instructions: List of next steps
|
|
914
|
+
"""
|
|
915
|
+
return self._execute_workflow(test_mode=False)
|
|
916
|
+
|
|
917
|
+
def _execute_workflow(self, test_mode: bool = False, test_only: bool = False) -> Dict[str, Any]:
|
|
918
|
+
"""
|
|
919
|
+
Execute the workflow script in either test or full mode.
|
|
920
|
+
|
|
921
|
+
Args:
|
|
922
|
+
test_mode: If True, run in test mode (single file), otherwise full batch
|
|
923
|
+
test_only: If True, stop after single file test (only used with test_mode=True)
|
|
806
924
|
"""
|
|
807
925
|
try:
|
|
808
926
|
workflow_script_path = self.folder_path / "1_masster_workflow.py"
|
|
809
927
|
|
|
810
|
-
# Check if workflow script exists
|
|
928
|
+
# Check if workflow script exists
|
|
811
929
|
if not workflow_script_path.exists():
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
930
|
+
return {
|
|
931
|
+
"status": "error",
|
|
932
|
+
"message": "Workflow script not found. Please run create_scripts() first.",
|
|
933
|
+
"instructions": [
|
|
934
|
+
"❌ Missing 1_masster_workflow.py",
|
|
935
|
+
"Run: wizard.create_scripts()",
|
|
936
|
+
"Then: wizard.run()"
|
|
937
|
+
]
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
# Setup execution mode
|
|
941
|
+
if test_only:
|
|
942
|
+
mode_label = "test-only"
|
|
943
|
+
elif test_mode:
|
|
944
|
+
mode_label = "test"
|
|
945
|
+
else:
|
|
946
|
+
mode_label = "full batch"
|
|
816
947
|
|
|
817
|
-
|
|
818
|
-
|
|
948
|
+
env = None
|
|
949
|
+
if test_mode:
|
|
950
|
+
import os
|
|
951
|
+
env = os.environ.copy()
|
|
952
|
+
env['MASSTER_TEST_MODE'] = '1'
|
|
953
|
+
if test_only:
|
|
954
|
+
env['MASSTER_TEST_ONLY'] = '1'
|
|
819
955
|
|
|
820
956
|
# Execute the workflow script
|
|
821
|
-
print(f"🚀 Executing
|
|
957
|
+
print(f"🚀 Executing {mode_label} processing workflow...")
|
|
822
958
|
print(f"📄 Running: {workflow_script_path.name}")
|
|
823
959
|
print("=" * 60)
|
|
824
960
|
|
|
825
961
|
import subprocess
|
|
826
962
|
result = subprocess.run([
|
|
827
963
|
sys.executable, str(workflow_script_path)
|
|
828
|
-
], cwd=str(self.folder_path))
|
|
964
|
+
], cwd=str(self.folder_path), env=env)
|
|
829
965
|
|
|
830
966
|
success = result.returncode == 0
|
|
831
967
|
|
|
832
968
|
if success:
|
|
833
969
|
print("=" * 60)
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
970
|
+
if test_only:
|
|
971
|
+
print("✅ Test-only processing completed successfully!")
|
|
972
|
+
print("📋 Single file validated - ready for full batch")
|
|
973
|
+
print(" wizard.run()")
|
|
974
|
+
elif test_mode:
|
|
975
|
+
print("✅ Test processing completed successfully!")
|
|
976
|
+
print("📋 Next step: Run full batch")
|
|
977
|
+
print(" wizard.run()")
|
|
978
|
+
else:
|
|
979
|
+
print("✅ Sample processing completed successfully!")
|
|
980
|
+
print("📋 Next step: Run interactive analysis")
|
|
981
|
+
print(" uv run marimo edit 2_interactive_analysis.py")
|
|
837
982
|
print("=" * 60)
|
|
838
983
|
|
|
984
|
+
next_step = ("Next: wizard.run()" if test_mode else
|
|
985
|
+
"Next: uv run marimo edit 2_interactive_analysis.py")
|
|
986
|
+
|
|
839
987
|
return {
|
|
840
988
|
"status": "success",
|
|
841
|
-
"message": "
|
|
989
|
+
"message": f"{mode_label.capitalize()} processing completed successfully",
|
|
842
990
|
"instructions": [
|
|
843
|
-
"✅
|
|
844
|
-
|
|
845
|
-
]
|
|
846
|
-
"files_created": []
|
|
991
|
+
f"✅ {mode_label.capitalize()} processing completed",
|
|
992
|
+
next_step
|
|
993
|
+
]
|
|
847
994
|
}
|
|
848
995
|
else:
|
|
849
996
|
return {
|
|
@@ -853,8 +1000,7 @@ class Wizard:
|
|
|
853
1000
|
"❌ Check the error messages above",
|
|
854
1001
|
"Review parameters in 1_masster_workflow.py",
|
|
855
1002
|
f"Try running manually: python {workflow_script_path.name}"
|
|
856
|
-
]
|
|
857
|
-
"files_created": []
|
|
1003
|
+
]
|
|
858
1004
|
}
|
|
859
1005
|
|
|
860
1006
|
except Exception as e:
|
|
@@ -865,8 +1011,7 @@ class Wizard:
|
|
|
865
1011
|
"❌ Execution failed",
|
|
866
1012
|
"Check that source files exist and are accessible",
|
|
867
1013
|
"Verify folder permissions"
|
|
868
|
-
]
|
|
869
|
-
"files_created": []
|
|
1014
|
+
]
|
|
870
1015
|
}
|
|
871
1016
|
|
|
872
1017
|
def _generate_script_content(self) -> str:
|
|
@@ -1175,198 +1320,6 @@ class Wizard:
|
|
|
1175
1320
|
return '\n'.join(script_lines)
|
|
1176
1321
|
|
|
1177
1322
|
|
|
1178
|
-
def create_script(
|
|
1179
|
-
source: str,
|
|
1180
|
-
folder: str,
|
|
1181
|
-
filename: str = 'run_masster.py',
|
|
1182
|
-
polarity: str = "positive",
|
|
1183
|
-
adducts: Optional[List[str]] = None,
|
|
1184
|
-
params: Optional[wizard_def] = None,
|
|
1185
|
-
num_cores: int = 0,
|
|
1186
|
-
**kwargs
|
|
1187
|
-
) -> bool:
|
|
1188
|
-
"""
|
|
1189
|
-
Create a standalone analysis script without initializing a Wizard instance.
|
|
1190
|
-
|
|
1191
|
-
This function generates a Python script that replicates automated processing
|
|
1192
|
-
steps with the specified configuration. The script can be executed independently
|
|
1193
|
-
to perform the same analysis.
|
|
1194
|
-
|
|
1195
|
-
Parameters:
|
|
1196
|
-
source: Directory containing raw data files
|
|
1197
|
-
folder: Output directory for processed study
|
|
1198
|
-
filename: Filename for the generated script (should end with .py)
|
|
1199
|
-
polarity: Ion polarity mode ("positive" or "negative")
|
|
1200
|
-
adducts: List of adduct specifications (auto-set if None)
|
|
1201
|
-
params: Custom wizard_def parameters (optional)
|
|
1202
|
-
num_cores: Number of CPU cores (0 = auto-detect)
|
|
1203
|
-
**kwargs: Additional parameters to override defaults
|
|
1204
|
-
|
|
1205
|
-
Returns:
|
|
1206
|
-
True if script was generated successfully, False otherwise
|
|
1207
|
-
|
|
1208
|
-
Example:
|
|
1209
|
-
>>> from masster.wizard import create_script
|
|
1210
|
-
>>> create_script(
|
|
1211
|
-
... source=r'D:\\Data\\raw_files',
|
|
1212
|
-
... folder=r'D:\\Data\\output',
|
|
1213
|
-
... filename='run_masster.py',
|
|
1214
|
-
... polarity='positive'
|
|
1215
|
-
... )
|
|
1216
|
-
"""
|
|
1217
|
-
|
|
1218
|
-
try:
|
|
1219
|
-
# Create parameters
|
|
1220
|
-
if params is not None:
|
|
1221
|
-
# Use provided params as base
|
|
1222
|
-
wizard_params = params
|
|
1223
|
-
# Update with provided values
|
|
1224
|
-
wizard_params.source = source
|
|
1225
|
-
wizard_params.folder = folder
|
|
1226
|
-
if polarity != "positive": # Only override if explicitly different
|
|
1227
|
-
wizard_params.polarity = polarity
|
|
1228
|
-
if num_cores > 0:
|
|
1229
|
-
wizard_params.num_cores = num_cores
|
|
1230
|
-
if adducts is not None:
|
|
1231
|
-
wizard_params.adducts = adducts
|
|
1232
|
-
else:
|
|
1233
|
-
# Create new params with provided values
|
|
1234
|
-
wizard_params = wizard_def(
|
|
1235
|
-
source=source,
|
|
1236
|
-
folder=folder,
|
|
1237
|
-
polarity=polarity,
|
|
1238
|
-
num_cores=max(1, int(multiprocessing.cpu_count() * 0.75)) if num_cores <= 0 else num_cores
|
|
1239
|
-
)
|
|
1240
|
-
|
|
1241
|
-
if adducts is not None:
|
|
1242
|
-
wizard_params.adducts = adducts
|
|
1243
|
-
|
|
1244
|
-
# Apply any additional kwargs
|
|
1245
|
-
for key, value in kwargs.items():
|
|
1246
|
-
if hasattr(wizard_params, key):
|
|
1247
|
-
setattr(wizard_params, key, value)
|
|
1248
|
-
|
|
1249
|
-
# Ensure study folder exists
|
|
1250
|
-
study_path = Path(folder)
|
|
1251
|
-
study_path.mkdir(parents=True, exist_ok=True)
|
|
1252
|
-
|
|
1253
|
-
# Create a temporary Wizard instance to generate the script
|
|
1254
|
-
temp_wizard = Wizard(params=wizard_params)
|
|
1255
|
-
|
|
1256
|
-
# Generate the scripts using the instance method
|
|
1257
|
-
result = temp_wizard.create_scripts()
|
|
1258
|
-
success = result.get("status") == "success"
|
|
1259
|
-
|
|
1260
|
-
return success
|
|
1261
|
-
|
|
1262
|
-
except Exception as e:
|
|
1263
|
-
print(f"Failed to create script: {e}")
|
|
1264
|
-
import traceback
|
|
1265
|
-
traceback.print_exc()
|
|
1266
|
-
return False
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
def execute(
|
|
1270
|
-
source: str,
|
|
1271
|
-
folder: str,
|
|
1272
|
-
filename: str = 'run_masster.py',
|
|
1273
|
-
polarity: str = "positive",
|
|
1274
|
-
adducts: Optional[List[str]] = None,
|
|
1275
|
-
params: Optional[wizard_def] = None,
|
|
1276
|
-
num_cores: int = 0,
|
|
1277
|
-
**kwargs
|
|
1278
|
-
) -> bool:
|
|
1279
|
-
"""
|
|
1280
|
-
Create and execute a standalone analysis script for automated MS data processing.
|
|
1281
|
-
|
|
1282
|
-
This function generates a Python script with the same parameters as create_script(),
|
|
1283
|
-
but immediately executes it after creation. Combines script generation and execution
|
|
1284
|
-
in a single step.
|
|
1285
|
-
|
|
1286
|
-
Parameters:
|
|
1287
|
-
source: Directory containing raw data files
|
|
1288
|
-
folder: Output directory for processed study
|
|
1289
|
-
filename: Filename for the generated script (should end with .py)
|
|
1290
|
-
polarity: Ion polarity mode ("positive" or "negative")
|
|
1291
|
-
adducts: List of adduct specifications (auto-set if None)
|
|
1292
|
-
params: Custom wizard_def parameters (optional)
|
|
1293
|
-
num_cores: Number of CPU cores (0 = auto-detect)
|
|
1294
|
-
**kwargs: Additional parameters to override defaults
|
|
1295
|
-
|
|
1296
|
-
Returns:
|
|
1297
|
-
True if script was created and executed successfully, False otherwise
|
|
1298
|
-
|
|
1299
|
-
Example:
|
|
1300
|
-
>>> from masster.wizard import execute
|
|
1301
|
-
>>> execute(
|
|
1302
|
-
... source=r'D:\\Data\\raw_files',
|
|
1303
|
-
... folder=r'D:\\Data\\output',
|
|
1304
|
-
... polarity='positive'
|
|
1305
|
-
... )
|
|
1306
|
-
"""
|
|
1307
|
-
|
|
1308
|
-
try:
|
|
1309
|
-
# First, create the script using create_script()
|
|
1310
|
-
script_created = create_script(
|
|
1311
|
-
source=source,
|
|
1312
|
-
folder=folder,
|
|
1313
|
-
filename=filename,
|
|
1314
|
-
polarity=polarity,
|
|
1315
|
-
adducts=adducts,
|
|
1316
|
-
params=params,
|
|
1317
|
-
num_cores=num_cores,
|
|
1318
|
-
**kwargs
|
|
1319
|
-
)
|
|
1320
|
-
|
|
1321
|
-
if not script_created:
|
|
1322
|
-
print("Failed to create analysis script")
|
|
1323
|
-
return False
|
|
1324
|
-
|
|
1325
|
-
# Get the full path to the created script
|
|
1326
|
-
study_path = Path(folder)
|
|
1327
|
-
script_path = study_path / Path(filename).name
|
|
1328
|
-
|
|
1329
|
-
if not script_path.exists():
|
|
1330
|
-
print(f"Script file not found: {script_path}")
|
|
1331
|
-
return False
|
|
1332
|
-
|
|
1333
|
-
print(f"Executing...")
|
|
1334
|
-
#print("=" * 70)
|
|
1335
|
-
|
|
1336
|
-
# Execute the script using subprocess with real-time output
|
|
1337
|
-
import subprocess
|
|
1338
|
-
|
|
1339
|
-
# Run the script with Python, letting it inherit our stdout/stderr
|
|
1340
|
-
try:
|
|
1341
|
-
# Use subprocess.run for direct output inheritance - no capturing/re-printing
|
|
1342
|
-
result = subprocess.run([
|
|
1343
|
-
sys.executable, str(script_path)
|
|
1344
|
-
], cwd=str(study_path))
|
|
1345
|
-
|
|
1346
|
-
return_code = result.returncode
|
|
1347
|
-
|
|
1348
|
-
except Exception as e:
|
|
1349
|
-
print(f"Error during script execution: {e}")
|
|
1350
|
-
return False
|
|
1351
|
-
|
|
1352
|
-
success = return_code == 0
|
|
1353
|
-
|
|
1354
|
-
if success:
|
|
1355
|
-
print("=" * 70)
|
|
1356
|
-
print("Script execution completed successfully")
|
|
1357
|
-
else:
|
|
1358
|
-
print("=" * 70)
|
|
1359
|
-
print(f"Script execution failed with return code: {return_code}")
|
|
1360
|
-
|
|
1361
|
-
return success
|
|
1362
|
-
|
|
1363
|
-
except Exception as e:
|
|
1364
|
-
print(f"Failed to execute script: {e}")
|
|
1365
|
-
import traceback
|
|
1366
|
-
traceback.print_exc()
|
|
1367
|
-
return False
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
1323
|
def create_scripts(
|
|
1371
1324
|
source: str = "",
|
|
1372
1325
|
folder: str = "",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: masster
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.17
|
|
4
4
|
Summary: Mass spectrometry data analysis package
|
|
5
5
|
Project-URL: homepage, https://github.com/zamboni-lab/masster
|
|
6
6
|
Project-URL: repository, https://github.com/zamboni-lab/masster
|
|
@@ -681,7 +681,6 @@ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
|
681
681
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
682
682
|
Requires-Python: >=3.11
|
|
683
683
|
Requires-Dist: alpharaw>=0.4.8
|
|
684
|
-
Requires-Dist: altair>=5.5.0
|
|
685
684
|
Requires-Dist: bokeh>=3.7.3
|
|
686
685
|
Requires-Dist: cmap>=0.6.2
|
|
687
686
|
Requires-Dist: datashader>=0.18.1
|
|
@@ -698,7 +697,6 @@ Requires-Dist: pandas>=2.2.0
|
|
|
698
697
|
Requires-Dist: panel>=1.7.0
|
|
699
698
|
Requires-Dist: polars>=1.0.0
|
|
700
699
|
Requires-Dist: pyopenms>=3.3.0
|
|
701
|
-
Requires-Dist: pyteomics>=4.7.0
|
|
702
700
|
Requires-Dist: pythonnet>=3.0.0
|
|
703
701
|
Requires-Dist: scikit-learn>=1.7.1
|
|
704
702
|
Requires-Dist: scipy>=1.12.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
masster/__init__.py,sha256=B7zftzdElF2Wb5B7KvkD6TONnMIY-Jxeen3s49dgmzs,1029
|
|
2
|
-
masster/_version.py,sha256=
|
|
2
|
+
masster/_version.py,sha256=KD2SEuC2rjv2RLni1gIwB7iF2uzGndbyPLJm7M_E38U,257
|
|
3
3
|
masster/chromatogram.py,sha256=iYpdv8C17zVnlWvOFgAn9ns2uFGiF-GgoYf5QVVAbHs,19319
|
|
4
4
|
masster/logger.py,sha256=XT2gUcUIct8LWzTp9n484g5MaB89toT76CGA41oBvfA,18375
|
|
5
5
|
masster/spectrum.py,sha256=TWIgDcl0lveG40cLVZTWGp8-FxMolu-P8EjZyRBtXL4,49850
|
|
@@ -67,9 +67,9 @@ masster/study/defaults/study_def.py,sha256=h8dYbi9xv0sesCSQik49Z53IkskMmNtW6ixl7
|
|
|
67
67
|
masster/wizard/README.md,sha256=mL1A3YWJZOefpJ6D0-HqGLkVRmUlOpwyVFdvJBeeoZM,14149
|
|
68
68
|
masster/wizard/__init__.py,sha256=L9G_datyGSFJjrBVklEVpZVLGXzUhDiWobtiygBH8vQ,669
|
|
69
69
|
masster/wizard/example.py,sha256=xEZFTH9UZ8HKOm6s3JL8Js0Uw5ChnISWBHSZCL32vsM,7983
|
|
70
|
-
masster/wizard/wizard.py,sha256=
|
|
71
|
-
masster-0.5.
|
|
72
|
-
masster-0.5.
|
|
73
|
-
masster-0.5.
|
|
74
|
-
masster-0.5.
|
|
75
|
-
masster-0.5.
|
|
70
|
+
masster/wizard/wizard.py,sha256=_co4abB8lNNryfqwS3AZtw6TGxw6NLowRjLXTUzJA0o,62994
|
|
71
|
+
masster-0.5.17.dist-info/METADATA,sha256=SnOZZo7h6E7XV_AIjomMkMYAwbibu23vZYyhQnRMEOM,45130
|
|
72
|
+
masster-0.5.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
73
|
+
masster-0.5.17.dist-info/entry_points.txt,sha256=ZHguQ_vPmdbpqq2uGtmEOLJfgP-DQ1T0c07Lxh30wc8,58
|
|
74
|
+
masster-0.5.17.dist-info/licenses/LICENSE,sha256=bx5iLIKjgAdYQ7sISn7DsfHRKkoCUm1154sJJKhgqnU,35184
|
|
75
|
+
masster-0.5.17.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|