Skip to content

Instantly share code, notes, and snippets.

@eteq
Last active December 18, 2015 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eteq/390a420c2b1ada60fc81 to your computer and use it in GitHub Desktop.
Save eteq/390a420c2b1ada60fc81 to your computer and use it in GitHub Desktop.
Hypothetical example for how parameter file schema might be defined. Annoyingly, it appears gists automatically re-order to alphabetical... But best to read this from the bottom file up to understand what's going on.
import schema_example # this schema gets created *on import* here
import astropfile
astropfile.engage('parfile_example') # runs all the tasks in the file
parset = astropfile.edit_params('parfile_example') # pops up a GUI/Web page that can edit the file
parset.engage() # actually runs the thing
parset = astropfile.edit_params(schema_example.fit_gaussian_to_echelle1) # same as above, but creates a GUI with the defaults
parset.engage()
parset.save('backup_param_file') # maybe the GUI also allows saving, but this way you can be sure it happens
parset.engage_string() # creates a string with python code that can be exec-ed
parset # in an ipython notebook, this would display them all in a pretty manner
# this could be done at the *command line*:
python -m astropfile parfile_example
- fit_gaussian_to_echelle1
- centerwl_guess : 6563 # will this fail b/c it's an integer? Or do we allow auto-casting to float when it makes sense?
- sig_guess : 15.
- amp_guess : 1.
- echelle_order : 5
# twice means just run it a second time but with different parameters
- fit_gaussian_to_echelle1
- centerwl_guess : 6563 # will this fail b/c it's an integer? Or do we allow auto-casting to float when it makes sense?
- sig_guess : 15.
- amp_guess : 1.
- echelle_order : 6
- fit_gaussian_to_echelle2
- centerwl_guess : 6563.
# can we get away with just that, b/c the function has defaults? Or do we require that everything have a parameter
# and only use the defaults when auto-creating?
#fit_gaussian_to_echelle3 should be identical to 2
- fit_gaussian_to_echelle_Q1
- centerwl_guess : Quantity
- value : 6563.
- unit : angstrom
# or can we get away with just this?:
- fit_gaussian_to_echelle_Q2
- centerwl_guess : 6563 angstrom
from astropfile import schema
@schema(centerwl_guess=float, sig_guess=float, amp_guess=float, echelle_order=int)
def fit_gaussian_to_echelle1(centerwl_guess, sig_guess, amp_guess, echelle_order):
...
# If there are defaults, guess the type based on what the defaults are
@schema(centerwl_guess=float)
def fit_gaussian_to_echelle2(centerwl_guess, sig_guess=0.5, amp_guess=1.0, echelle_order=5):
...
# But can always override if necessary
@schema(centerwl_guess=float, amp_guess=float)
def fit_gaussian_to_echelle3(centerwl_guess, sig_guess=0.5, amp_guess=1, echelle_order=5):
...
# Should also allow the possibility of more complicated objects getting passed in
@schema(center_guess=Quantity)
def fit_gaussian_to_echelle_Q1(center_guess, sig_guess=0.5*u.nm, amp_guess=1., echelle_order=5):
# note that now center_guess doesn't have to be a wavelength - if the user passes in a frequency it could be
# auto-converted by this function, because Quantity has unit information baked in
...
# Bonus: allow Quantities to be specific physical types. Astropy already has machinery to do this so we
# could probably hook into that
from astropy import units as u
@schema(center_guess=u.angstrom) # giving a unit implies a Quantity?
def fit_gaussian_to_echelle_Q2(center_guess, sig_guess=0.5*u.nm, amp_guess=1, echelle_order=5):
# note that now center_guess doesn't have to be a wavelength - if the user passes in a frequency it could be
# auto-converted by this function, because Quantity has unit information baked in
...
@sosey
Copy link

sosey commented Dec 10, 2015

You could be even a little more specific and require classes and validate the values in function properties, I think this is valid in python3

class fit_gaussian_to_eschelle(object):
def init(self, center_guess=0, sig_guess=0.5, amp_guess=1, echelle_order=1):
self.center_guess = center_guess
self.sig_guess = sig_guess
self.amp_guess = amp_guess
self.echelle_order = echelle_order

@Property
def center_guess(self):
"""I am the center guess""
return self._center_guess

@center_guess.setter
def center_guess(self, guess):
if not guess: raise Exception("You must provide a center guess")
if isinstance(guess,str): raise Exception("No strings allowed!")
if (guess < 0): raise Exception("Center guess must be greater than zero")
self.center_guess=guess

and so on.... even if someone bypasses the parameter file and calls the object directly it will throw an exception on import when it makes the object if the parameters are unallowed I think. Your yaml file would still look the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment