Closed drvdputt closed 1 year ago
mymiri.meta['instrument'] = 'jwst.miri.ch1.A'
Hoping this step will be provided by JWST pipeline itself at some point.
mymod.guess(fancy_guess=True, ...)
You will have to pass the spectrum/iterable of spectra to guess
. I'd also just use an optional positional argument for plot.
The line widths are not stored in the features table
The only exception being lines which have bounds specified for FWHM, either by the user directly on the Feature table itself, or indirectly by using multi-instrument specifiers.
This looks like a great overall setup.
I have put something together for the new interface, close to working. For now, param_info is generated as an intermediate step wherever needed. For example, I have the function
def _construct_astropy_model(self):
"""Convert the features table into a fittable model."""
param_info = self._kludge_param_info()
return PAHFITBase.model_from_param_info(param_info)
which uses the old code like this
def _kludge_param_info(self):
param_info = PAHFITBase.parse_table(self.features)
# edit line widths and drop lines out of range
param_info[2] = PAHFITBase.update_dictionary(
param_info[2], self.instrumentname, update_fwhms=True
)
param_info[3] = PAHFITBase.update_dictionary(
param_info[3], self.instrumentname, update_fwhms=True
)
return param_info
The main thing I still have to work on (as far as functionality goes) is a function I've called Model._parse_astropy_result(self, astropy_model):
, which will update the features table based on a fit result. This should be relatively straightforward, as the names of the astropy model components and those in the name column of the features table are the same by construction.
There is one exception though, so here's a question:
Why is the attenuation named "S07_att" in the astropy model, and "silicate" in the features table? Can I change the code so that it's just "silicate" everywhere? This renaming happens like this by the way
if att_info["names"] == 'silicate':
name_array = np.array(['S07_att'])
att_info.update({'names': name_array})
This is great, thanks Dries. Hopefully the user will never have to "handle" a param_info dict, but instead the API will generate it and pass it along where it's needed under cover.
For attenuation, I'd strongly suggest keying on kind=attenuation
. And in general (where possible) prefer kind
over the names, since names are an arbitrary convenience, and up to the user, who may in fact develop their own custom science pack. As we were discussing on Monday, we will likely branch out beyond the original hand-crafted PAHFIT attenuation curve (=S07), to provide access to others. So any reference to that specific curve isn't meaningful.
Hopefully the user will never have to "handle" a param_info dict, but instead the API will generate it and pass it along where it's needed under cover.
This is exactly how I'm doing it. param_info
is not even stored anywhere. It is purely an implementation detail, existing only as a temporary variable, bridging PAHFITBase.parse_table() --> param_info --> PAHFITBase.model_from_param_info(param_info)
.
prefer kind over the names
I'm using the names because they are unique identifiers, mapping components of the astropy model to lines in the features table.
So any reference to that specific curve isn't meaningful.
The current implementation for creating the attenuation component of the model does this
for k in range(len(att_info["names"])):
if (
att_info["names"][k] == "S07_att"
): # Only loop through att components that can be parameterized
model *= S07_attenuation(
name=att_info["names"][k],
tau_sil=att_info["amps"][k],
bounds={"tau_sil": att_info["amps_limits"][k]},
fixed={"tau_sil": att_info["amps_fixed"][k]},
)
else:
model *= att_Drude1D(
name=att_info["names"][k],
tau=att_info["amps"][k],
x_0=att_info["x_0"][k],
fwhm=att_info["fwhms"][k],
bounds={
"tau": att_info["amps_limits"][k],
"fwhm": att_info["fwhms_limits"][k],
},
fixed={"x_0": att_info["x_0_fixed"][k]},
which relies on that specific name to decide between the S07 model and generic drude feature attenuation. A quick fix would be to change the structure of att_info (the last element of param_info).
Also, since the features table contains a 'model' column, with 'S07_attenuation' as an example, we should obviously use that one instead of the name to decide which attenuation model to make.
Question: is the drude based attenuation model used by anyone? Or can we just remove this functionality? Would make things easier.
Yes, Drude attenuation is used for ice and other absorption in the 2-6µm range. These features have kind=absorption
in the new YAML scipack, and there can be arbitrary numbers of them (perhaps grouped). There can be only one kind=attenuation
so that should simplify things. Using the names internally to keep track of things is fine, but do not hard-code them, since they are arbitrary. For attenuation
, model
is future-proofing, for when we have more models available. For now feel free to ignore "model" and just hard-code the S07 curve.
It is honestly a little annoying to have two full columns of the feature table allocated to one feature (attenuation). Open to ideas on this.
model *= S07_attenuation(...
model *= att_Drude1D(...
BTW, this is the specific piece of code @ThomasSYLai and I were discussing on Monday: whether model should accumulate by multiplication, or instead tau should accumulate by addition. For now just leave as is.
Also, for power
are you just going to treat it as a curve amplitude, or did we converge on PR #225?
I was trying to make the att_info object a bit more generic, but based on your above comment (that there can be only one attenuation model), I will keep things as-is. Once we start having more complicated attenuation things, I think it would be easier to re-write the table parsing from scratch, instead of sticking with the param_info method, and having to tailor everything to it.
As far as power goes: I am keeping the meaning of the parameters the same for now, so for now it will stay the same as amplitude.
If a simple value conversion (for input/output purposes) suffices, then it can be implemented in _parse_astropy_result (just as I did for the conversion between fwhm and stddev).
If we want the fit to behave differently, then AreaGaussian and AreaDrude will need to be used (perhaps this is another use for the 'model' column?)
Right, let's go quick and simple to get something working with the new API for now. If #225 models are working, we can switch to those at some point, but not this in PR. Thanks!
The easiest thing I could come up with was to add an extra member to param_info. Now att_info has been split up into abs_info and att_info. This makes things easier, because the former are all drudes, and the latter is the one attenuation model we have.
As soon as the YAML-based science packs are in working order (#222 ), I will start working on the new interface. I am posting the current draft here for reference, with some comments as to what should be going on under the hood.
A couple of use cases providing constraints