This is the data reduction pipeline for the Nancy Grace Roman Space Telescope Coronagraph Instrument
As the code is very much still in development, clone this repository, enter the top-level folder, and run the following command:
pip install -e .
Then you can import corgidrp
like any other python package!
The installation will create a configuration folder in your home directory called .corgidrp
.
That configuration directory will be used to locate things on your computer such as the location of the calibration database and the pipeline configuration file. The configuration files stores setting such as whether to track each individual error term added to the noise.
Large binary files (used in tests) are stored in Git LFS. Install Git LFS if it isn't already installed. You may need to run git lfs pull
after checking out the repository to download the latest large binary files, or the unit tests may fail.
To run the existing end-to-end tests, you also need the II&T code, which is used directly for comparing results. This also requires Git LFS to be installed first. Then install the II&T code by doing the following while in the top-level folder:
pip install -r requirements_e2etests.txt corgidrp
This will install the II&T repositories cal
and proc_cgi_frame
.
If you run into any issues with things in the .corgidrp
directory not being found properly when you run the pipeline, such as a DetectorParams file, caldb, or configuration settings, your corgidrp is configured into a weird state. Report the bug to our Github issue tracker that includes both the error message, and the state of your .corgidrp
folder. If you don't want to wait for us to troubleshoot the bug and deploy a fix, you can probably resolve the issue by completely deleting your .corgidrp
folder and rerunning the code (the code will automatically remake it). This however means you will lose any changes you've made to your settings as well as your calibration database.
We encourage you to chat with Jason, Max, and Marie (e.g., on Slack) to discuss what to do before you get started. Brainstorming about how to implement something is a very good use of time and makes sure you aren't going down the wrong path. Contact Jason is you have any questions on how to get started on programming details (e.g., git).
Below is a quick tutorial that outlines the general contribution process.
Check out the Github issues page for tasks that need attention. Alternatively, contact Jason (@semaphoreP). Make sure to tag yourself on the issue and mention in the comments if you start working on it.
See install instructions above. Contact Jason (@semaphoreP) if you need write access to push changes as you make edits. If you do not have write access to the repository, you can still contribute by creating a fork of the repository under your own GitHub user. See here for details: https://docs.github.com/en/get-started/quickstart/fork-a-repo. You can then use the same commands given below, but just replace roman-corgi
with your own GitHub username. If you fork the repository, you will need to make sure that your fork is up to date with the main repository (https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork).
To quickly get up an running with the repository, execute the following commands in a terminal (or command prompt - you will need to have the git executable installed on your system):
> git clone https://github.com/roman-corgi/corgidrp.git
> cd corgidrp
> pip install -e .
You will create a "feature branch" so you can develop your feature without impacting other people's code. Let's say I'm working on dark subtraction. I could create a feature branch and switch to it like this
> git branch dark-sub
> git checkout dark-sub
In corgidrp
, each pipeline step is a function, that is contained in one of the lX_to_lY.py files (where X and Y are various data levels).
Think about how your feature can be implemented as a function that takes in some data and outputs processed data. Please see below for some
corgidrp
design principles.
All functions should follow this example:
def example_step(dataset, calib_data, tuneable_arg=1, another_arg="test"):
"""
Function docstrings are required and should follow Google style docstrings.
We will not demonstrate it here for brevity.
"""
# unless you don't alter the input dataset at all, plan to make a copy of the data
# this is to ensure functions are reproducible
processed_dataset = input_dataset.copy()
### Your code here that does the real work
# here is a convience field to grab all the data in a dataset
all_data = processed_dataset.all_data
### End of your code that does the real work
# update the header of the new dataset with your processing step
history_msg = "I did an example step"
# update the output dataset with the new data and update the history
processed_dataset.update_after_processing_step(history_msg, new_all_data=all_data)
# return the processed data
return processed_dataset
Inside the function can be nearly anything you want, but the function signature and start/end of the function should follow a few rules.
You can check out corgidrp.l2a_to_l2b.dark_subtraction
function as an example of a basic pipeline step.
We are required to write tests to verify the functionality of the code. Instead of seeing this as an extra chore, I encourage you to write unit tests to be your debug script to get your code working (this is called "test-driven development").
All tests are stored in the tests
folder and each test is a function that starts with test_
. See tests/test_dark_sub.py
as an example. Within each test, you will likely need to simulate some mock data, run it through your function you wrote, and verify it ran correctly using assert statements. Your tests should cover the primary use cases of your code, and check that the function outputs what you expect. You do not need high fidelity data for your test: focus on making sure the data is in the correct format as real data, and less on making sure the data values are simulated to high fidelity (see the examples in the mocks.py
module).
Importantly, these tests will allow code reviewers to test and understand your code. We will also run these tests in an automated test suite (continuous integration) with the pipeline to verify the functions continue to work (e.g., as dependencies change).
You can either run tests individually yourself (to debug individual tests) or run the entire test suite to make sure you didn't break anything.
To run an individual test, call the test function you want to test at the bottom of its test_*.py
script. Then, you just need to run the test_*.py
script. See tests/test_dark_sub.py
for an example.
To run all the tests in the test suite, go to the base corgidrp folder in a terminal and run the pytest
command.
End-to-end testing refers to processing data as one would when we get the real data (i.e., starting from L1 data). If applicable, write an end-to-end test following the l1_to_l2a_e2e.py
and l1_to_l2b_e2e.py
examples in the tests/e2e_tests
folder. For example, if you wrote a step that generates a calibration function, write an end-to-end test that produces the calibration file from L1 data. The steps are as follows:
corgidrp/recipe_templates
as examples and double check all the necessary steps in the FDD. corgidrp.walker.guess_template()
function to add logic for determining when to use your recipe based on header keywords (e.g., VISTYPE). Ask Jason, who developed this framework, if it is not clear what should be done. tests/e2e_tests/l1_to_l2b_e2e.py
for examples of how to do this for each type of calibration)tests/e2e_tests/
for how to structure this script. You should only need to write a single script./usr/bin/time -v python your_e2e_test.py
and Mac userse can run /usr/bin/time -l -h -p python <your_e2e_test.py>
. Record elapsed (wall clock) time, the percent of CPU this job got (only if parallelization was used), and total memory used (labelled "Maximum resident set size"). To run the existing end-to-end tests, you need to have downloaded all the TVAC data to your computer. In a terminal, go to the base directory of the corgidrp repo and run the following command, substituting paths for paths on your computer as desired:
pytest --which e2e --tvacdata_path /path/to/CGI_TVAC_Data --e2eoutput_path tests/e2e_tests/ tests/e2e_tests/
In addition to unit tests, your code will need to pass a static analysis before being merged. corgidrp
currently runs a subset of flake8 tests, which you can replicate on your local system by running:
flake8 . --count --select=E9,F63,F7,F82,DCO020,DCO021,DCO022,DCO023,DCO024,DCO030,DCO031,DCO032,DCO060,DCO061,DCO062,DCO063,DCO064,DCO065 --show-source --statistics
from the top-level directory of the repository. In order to run these tests you will need to have flake8
and flake8-docstrings-complete
installed (both are pip-installable). Note that the test subset may be updated in the future. To see the current set of tests being applied, look in the continuous integration GitHub action, located in the repository in file .github/workflows/python-app.yml
.
Before creating a pull request, review the design Principles below. Use the Github pull request feature to request that your changes get merged into the main
branch. Assign Jason/Max to be your reviewers. Your changes will be reviewed, and possibly some edits will be requested. You can simply make additional pushes to your branch to update the pull request with those changes (you don't need to delete the PR and make a new one). When the branch is satisfactory, we will pull your changes in. When preparing your pull request, you may find it helpful to follow this checklist:
flake8
command given abovenumpy
, scipy
or Astropy
. If you think you need to use something else, please check with Jason and Max. corgidrp.Data
class, it will have a save()
function that will be used.Image
class, and you can look at the Dark
class as an example. Each calibration type should have its own Image
subclass defined. Talk with Jason and Max to discuss how your class should be implemented!Image
class. If you need to copy calibration objects at all you can import and apply the copy module of python, see
example:
import copy
flatfield = data.Flatfield('flatfield.fits')
#reference copy
flatfield_copy = copy.copy(flatfield)
#deep data copy
flatfield_copy = copy.deepcopy(flatfield)
What python version should I develop in?
How should I treat different kinds of function parameters:
Where should I store computed variables so they can be referenced later in the pipeline?
Where do I save FITS files or other data files I need to use for my tests?
git lfs
. Ask Jason about setting up git lfs (as of writing, we have not set up git lfs yet).v1.1.1
v1.1
v1.0
v0.2.1
v0.2
v0.1.2
v0.1