Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.log
__pycache__
**/__pycache__/
.venv
.venv
.ipynb_checkpoints
109 changes: 0 additions & 109 deletions .ipynb_checkpoints/README-checkpoint.md

This file was deleted.

1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.10
53 changes: 42 additions & 11 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,44 @@ Version 2.0 - 2025-??-?? (RT)
importlib.resources.

- runtask.py: File has been removed and all functionality has been transferred to
sastask.py. It only added an extra layer to the process.
sastask.py. It only added an extra layer to the process.

+ sastask.py: The class SASTask has been deprecated since it was only an abstract class,
with only abstract methods and a single child, MyTask. MyTask was the only
class used in the rest of the code. To simplify things, MyTask has been
made the only useful class, but SASTask is declared as a child of MyTask
with only abstract methods and a single child, MyTask. MyTask was the only
class used in the rest of the code. To simplify things, MyTask has been
made the only useful class, but SASTask is declared as a child of MyTask
for legacy purposes, until all references to it can be removed.

Functionality from runtask has been placed in the 'run' method in MyTask.
Functionality from runtask has been placed in the 'run' method in MyTask.
The method 'runtask' has been kept as a place holder for legacy code. It
just calls 'run'.

Changed how options that affect environment variables are handled. For
Python based SAS tasks, pySAS will *temporarily* change the environment
variables, run the task, and then restore the environment variables to
their previous setting. For non-Python based SAS tasks, these options are
passed to the subprocess command to run the task.

Options that will execute and exit are:
-v (version)
-h (help)
-p (param)
-d (dialog)
-m (manpage)

For **only** Python based tasks:
Options that will *temporarily* set environment variables are:
-V (SAS_VERBOSITY)
-a (SAS_CCFPATH)
-i (SAS_CCF)
-o (SAS_ODF)

Options that are not handled for Python based SAS tasks (but are
passed to the task in 'iparsdic', so in principle they can be used.)
-f/--ccffiles
-w/--warning
-t/--trace

- wrapper.py: The Wrapper class has been deprecated since its only function was to create
a MyTask object. It has been left in place until legacy code can be switched
over to MyTask.
Expand All @@ -31,14 +57,14 @@ Version 2.0 - 2025-??-?? (RT)
'get_logger' function, but through the MyTask object which accepts all
necessary inputs.

The user can declare a directory for the log files, or even a single log file
The user can declare a directory for the log files, or even a single log file
for all output from all SAS tasks called.

+ version.py: At the top level version.py only contains the version information for pySAS.
For independent tasks they maintain their own version numbers, but for all
other subdirectories they all point to the master pySAS version file.

get_sas_version dedicated function to run 'sasversion' and get SAS version
get_sas_version dedicated function to run 'sasversion' and get SAS version
information.

+ */version.py: All version files for individual SAS tasks now only contain their version
Expand All @@ -57,9 +83,14 @@ Version 2.0 - 2025-??-?? (RT)
they cannot be used by the end user.

+ obsid : obsid.py introduced. Replaces odfcontrol.
Significant changes to pySAS. Three new classes (Parent with two children):
1. ObsID (Parent class)
2. ODF (Child class of ObsID)
3. PPS (Child class of ObsID)
Significant changes to pySAS. New class: ObsID

+ parser.py : Update documentation, add logger to ParseArgs, changed 'taskparser' to
'optparser'. 'procopt' has been split into 'exe_options' and
'env_options' to handle options that require immediate action
(exe_options), and options that handle environment variables
(env_options).

+ param.py : Update documentation, add logger to paramXmlInfoReader.


8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ It is recommended that you add this line to your .bash_profile file (or equivele

There are example scripts and Jupyter notebooks available on [GitHub demonstrating how to use pySAS](https://github.com/XMMGOF/pysas/tree/main/documentation). We are expanding the number of example scripts and Jupyter notebooks.

### Contributing to PySAS

We are using the package manager [uv](https://docs.astral.sh/uv/). This way every developer has the same python and package versions. Before editing the code, install uv ([installing uv](https://docs.astral.sh/uv/getting-started/installation/)) on your machine.

When you have uv installed, `cd` into the root directory of `pysas` in your favorite terminal and execute `uv sync`. This will create a `.venv` directory in the root directory, which contains all the packages. Point your IDE to use `.venv/bin/python` as the python executable for this project.

One of the installed packages is [`pre-commit`](https://pre-commit.com), but it is not yet initialized. This will be done in near future.

### FAQ

Q: Will this break my SAS inatallation?
Expand Down
89 changes: 57 additions & 32 deletions documentation/.ipynb_checkpoints/Basics_of_pySAS-checkpoint.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,42 @@
"```python\n",
"from pysas.sastask import MyTask\n",
"```\n",
"`MyTask` takes two inputs, the first is the name of the SAS task as a string. The second is a list with the input arguments for the SAS task. Each input argument must be a string. If there are no input arguments then the list will be empty:\n",
"`MyTask` takes two inputs, the first is the name of the SAS task as a string. The second is a dictionary with the input arguments for the SAS task. If there are no input arguments then the dictionary will be empty:\n",
"```python\n",
"MyTask('sasver', []).run()\n",
"MyTask('sasversion', {}).run()\n",
"```\n",
"\n",
"Each input argument must be a separate string in the list:\n",
"Each input argument will take the form of a 'key' (parameter name) and 'value' (parameter value) pair. Each parameter value should be a single string.\n",
"```python\n",
"inargs = ['table=event_list.fits', \n",
" 'withfilteredset=yes', \n",
" \"expression='(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\", \n",
" 'filteredset=filtered_event_list.fits', \n",
" 'filtertype=expression', \n",
" 'keepfilteroutput=yes', \n",
" 'updateexposure=yes', \n",
" 'filterexposure=yes']\n",
"inargs = {'table' : 'event_list.fits',\n",
" 'withfilteredset' : 'yes',\n",
" \"expression\" : \"'(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\",\n",
" 'filteredset' : 'filtered_event_list.fits',\n",
" 'filtertype' : 'expression', \n",
" 'keepfilteroutput': 'yes',\n",
" 'updateexposure' : 'yes',\n",
" 'filterexposure' : 'yes'}\n",
"\n",
"MyTask('evselect', inargs).run()\n",
"```\n",
"<div class=\"alert alert-block alert-warning\">\n",
" <b>Note:</b> Some inputs require single quotes to be preserved in the string. This can be done using double quotes to form the string. i.e. \"expression='(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\"\n",
"</div>"
" <b>Note:</b> Some inputs require single quotes to be preserved in the string. This can be done using double quotes to form the string. i.e. \"'(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\"\n",
"</div>\n",
"\n",
"If you need to pass in command line options to a SAS task, add it to the dictionary with they key '`options`'. For example,\n",
"```python\n",
"inargs = {'options' : '--verbosity 6 --noclobber'\n",
" 'table' : 'event_list.fits',\n",
" 'withfilteredset' : 'yes',\n",
" \"expression\" : \"'(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\",\n",
" 'filteredset' : 'filtered_event_list.fits',\n",
" 'filtertype' : 'expression', \n",
" 'keepfilteroutput': 'yes',\n",
" 'updateexposure' : 'yes',\n",
" 'filterexposure' : 'yes'}\n",
"\n",
"MyTask('evselect', inargs).run()\n",
"```"
]
},
{
Expand Down Expand Up @@ -270,25 +285,10 @@
"id": "9d88b1a4-026a-45d4-b707-f026959c6e02",
"metadata": {},
"source": [
"As noted above, for all SAS tasks, input arguments should be in a list, with each input argument a separate string. \n",
"As noted above, for all SAS tasks, input arguments should be in dictionary, with each parameter value a single string. \n",
"\n",
"For example,\n",
"```python\n",
"inargs = ['table=event_list.fits', \n",
" 'withfilteredset=yes', \n",
" \"expression='(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\", \n",
" 'filteredset=filtered_event_list.fits', \n",
" 'filtertype=expression', \n",
" 'keepfilteroutput=yes', \n",
" 'updateexposure=yes', \n",
" 'filterexposure=yes']\n",
"\n",
"MyTask('evselect', inargs).run()\n",
"```\n",
"\n",
"The development version of pySAS allows inputs to be passed in as a Python dictionary. For example, the same list of input arguments shown above could be written like this:\n",
"\n",
"```python\n",
"inargs = {'table' : 'event_list.fits', \n",
" 'withfilteredset' : 'yes', \n",
" 'expression' : \"'(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\", \n",
Expand All @@ -300,7 +300,6 @@
"\n",
"MyTask('evselect', inargs).run()\n",
"```\n",
"\n",
"or it could even be written like this:\n",
"\n",
"```python\n",
Expand All @@ -324,9 +323,21 @@
"MyTask('evselect', inargs).run()\n",
"```\n",
"\n",
"The reason why this capability was added was for experimental reasons and to allow greater flexibility in interacting with pySAS.\n",
"For versions of pySAS before v2.0, the input arguments were passed in as a list. And in pySAS v2.0 you can still pass in the input arguments as a list.\n",
"```python\n",
"inargs = ['table=event_list.fits', \n",
" 'withfilteredset=yes', \n",
" \"expression='(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\", \n",
" 'filteredset=filtered_event_list.fits', \n",
" 'filtertype=expression', \n",
" 'keepfilteroutput=yes', \n",
" 'updateexposure=yes', \n",
" 'filterexposure=yes']\n",
"\n",
"While the values for all input arguments should be in string format, the development version of pySAS will accept numbers, as shown below. These numbers will be converted into strings automatically.\n",
"MyTask('evselect', inargs).run()\n",
"```\n",
"\n",
"While the values for all input arguments should be in string format, pySAS v2.0 will accept numbers, as shown below. These numbers will be converted into strings automatically.\n",
"\n",
"```python\n",
"inargs = {}\n",
Expand All @@ -340,6 +351,20 @@
"MyTask('rgsrmfgen', inargs).run()\n",
"```\n",
"\n",
"Also in pySAS v2.0 'yes/no' parameters can be passed in as a boolean:\n",
"```python\n",
"inargs = {'table' : 'event_list.fits', \n",
" 'withfilteredset' : True, \n",
" 'expression' : \"'(PATTERN <= 12)&&(PI in [200:4000])&&#XMMEA_EM'\", \n",
" 'filteredset' : 'filtered_event_list.fits', \n",
" 'filtertype' : 'expression', \n",
" 'keepfilteroutput' : True, \n",
" 'updateexposure' : True, \n",
" 'filterexposure' : True}\n",
"\n",
"MyTask('evselect', inargs).run()\n",
"```\n",
"\n",
"The user can get all the default parameters for any SAS task by using:\n",
"```python\n",
"task_name = 'insert_task_name'\n",
Expand Down
Loading