Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Explore refactor using a lower-level Function class #15

Open
marshallmcdonnell opened this issue Dec 10, 2018 · 1 comment
Open

Explore refactor using a lower-level Function class #15

marshallmcdonnell opened this issue Dec 10, 2018 · 1 comment
Labels

Comments

@marshallmcdonnell
Copy link
Member

To better improve the design and checks for the higher-level classes, specifically the Converter class, would like to explore the idea of a Function class that acts like a factory.

The idea of the class would be something like:

sq = Function(x, y, error=e, "S(Q)") # x,y,e are the Q, S(Q), and E[S(Q)], respectively
dcs = sq.to_DCS()
gr = sq.to_GofR(r) # r is the real space domain

Yet, the initial issue I see is that this requires both the capabilities of the Converter and Transformer into one class.

@marshallmcdonnell
Copy link
Member Author

I think a better approach will be to do a modified Translator pattern mixed with borrowing from ASE's functional approach to I/O.

I would like to have a high-level function convert instead of a class of functions (i.e. Converter).
An example would be:

import numpy as np
from pystog import convert
q = np.arange(0., 10.0, 0.1)
sq = np.random.rand(100)

q, dcs = convert(q, sq, from="S(Q)", to="DCS(Q)")

Behind the scenes, the from and to arguments would belong to dictionaries for the different function types.
Something similar in ASE is the define_io_format that maps strings to module names. (this fills in the ioformats dictionary in ASE)

Each module of ours will be real functions with to_gofr and from_gofr function and reciprocal functions with to_sofq and from_sofq (similarly to the read_* and write_* functions in ASE; see xyz example)

Based on the from and to we can:

  1. Figure out if they exist in the real space or reciprocal space dictionary of patterns supported
  2. Make sure they come from the same dictionary / function space
  3. Get the module to load for the from conversion to either G(r) (to_gofr function) or S(Q) (to_sofq function)
  4. Get the module to load for the to conversion from either G(r) (from_gofr function) or S(Q) (from_sofq function)

In ASE, the module lookup is accomplished via the _writefunc and _readfunc functions. These are then used by the _read_wrapper and _write_wrapper functions.

Then, I see the directory structure taking on (including a transform and fouier_filter function refactor, too) the following:

├── convert.py
├── fourier_filter.py
├── functions
│   ├── gofr.py
│   ├── real
│   │   ├── gk_of_r.py
│   │   └── small_g_of_r.py
│   ├── reciprocal
│   │   ├── dcs_of_q.py
│   │   ├── fk_of_q.py
│   │   └── f_of_q.py
│   └── sofq.py
└── tranform.py

All the files under the functions directory are the top-level G(r) and S(Q) followed by real and reciprocal space sub sets that hold these from_* and to_*.

Thus, we have a translator pattern using G(R) and S(Q) as our "common objects"

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant