Commit dc400d5620c31401c560fd81cdaed79abad7e503
1 parent
e55c60c7
ported residual computation to obsutils
Showing
2 changed files
with
96 additions
and
59 deletions
cscripts/csresmap.py
| ... | ... | @@ -19,9 +19,9 @@ |
| 19 | 19 | # |
| 20 | 20 | # ========================================================================== |
| 21 | 21 | import sys |
| 22 | -import math | |
| 23 | 22 | import gammalib |
| 24 | 23 | import ctools |
| 24 | +from cscripts import obsutils | |
| 25 | 25 | |
| 26 | 26 | |
| 27 | 27 | # ============== # |
| ... | ... | @@ -209,67 +209,15 @@ class csresmap(ctools.csobservation): |
| 209 | 209 | # Get model map into GSkyMap object |
| 210 | 210 | modelmap = model.cube().counts().copy() |
| 211 | 211 | |
| 212 | - # Store counts map as residual map. Note that we need a special | |
| 212 | + # Calculate residual maps | |
| 213 | + # Note that we need a special | |
| 213 | 214 | # construct here to avoid memory leaks. This seems to be a SWIG feature |
| 214 | 215 | # as SWIG creates a new object when calling binning.cube() |
| 215 | - self._resmap = countmap.copy() | |
| 216 | - self._resmap.stack_maps() | |
| 216 | + countmap1 = countmap.copy() | |
| 217 | + countmap1.stack_maps() | |
| 218 | + print("TEST",countmap1.classname()) | |
| 217 | 219 | modelmap.stack_maps() |
| 218 | - | |
| 219 | - # Get residual map algorithm type | |
| 220 | - algorithm = self['algorithm'].string() | |
| 221 | - | |
| 222 | - # Subtract maps | |
| 223 | - if algorithm == 'SUB': | |
| 224 | - self._resmap -= modelmap | |
| 225 | - | |
| 226 | - # Subtract and divide by model map | |
| 227 | - elif algorithm == 'SUBDIV': | |
| 228 | - self._resmap -= modelmap | |
| 229 | - self._resmap /= modelmap | |
| 230 | - | |
| 231 | - # Subtract and divide by sqrt of model map | |
| 232 | - elif algorithm == 'SUBDIVSQRT': | |
| 233 | - self._resmap -= modelmap | |
| 234 | - self._resmap /= modelmap.sqrt() | |
| 235 | - | |
| 236 | - # Calculate significance from Li&Ma derivation | |
| 237 | - elif algorithm == 'SIGNIFICANCE': | |
| 238 | - | |
| 239 | - # Compute sign map | |
| 240 | - signmap = (self._resmap - modelmap).sign() | |
| 241 | - | |
| 242 | - # Loop over every bin in the map | |
| 243 | - for i in range(self._resmap.npix()): | |
| 244 | - | |
| 245 | - # If the model value > 0.0 do the computation as normal ... | |
| 246 | - model_val = modelmap[i] | |
| 247 | - if model_val > 0.0: | |
| 248 | - | |
| 249 | - # If the data value is also > 0 then compute the | |
| 250 | - # significance^2 and save it to the map ... | |
| 251 | - data_val = self._resmap[i] | |
| 252 | - if data_val > 0.0: | |
| 253 | - log_val = math.log(data_val/model_val) | |
| 254 | - self._resmap[i] = (data_val*log_val) + model_val - data_val | |
| 255 | - | |
| 256 | - # ... otherwise compute the reduced value of the above | |
| 257 | - # expression. This is necessary to avoid computing log(0). | |
| 258 | - else: | |
| 259 | - self._resmap[i] = model_val | |
| 260 | - | |
| 261 | - # ... otherwise hard-code the significance to 0 | |
| 262 | - else: | |
| 263 | - self._resmap[i] = 0.0 | |
| 264 | - | |
| 265 | - # Compute significance map | |
| 266 | - self._resmap *= 2.0 | |
| 267 | - self._resmap = self._resmap.sqrt() | |
| 268 | - self._resmap = self._resmap * signmap | |
| 269 | - | |
| 270 | - # Raise exception if algorithm is unknown | |
| 271 | - else: | |
| 272 | - raise TypeError('Algorithm "'+algorithm+'" not known') | |
| 220 | + self._resmap = obsutils.residuals(self,countmap1,modelmap) | |
| 273 | 221 | |
| 274 | 222 | # Optionally publish map |
| 275 | 223 | if self['publish'].boolean(): | ... | ... |
cscripts/obsutils.py
| ... | ... | @@ -828,3 +828,92 @@ def get_onoff_obs(cls, obs): |
| 828 | 828 | |
| 829 | 829 | # Return On/Off oberservation container |
| 830 | 830 | return onoff_obs |
| 831 | + | |
| 832 | +# ========================================= # | |
| 833 | +# Calculate residuals from counts and model # | |
| 834 | +# ========================================= # | |
| 835 | +def residuals(cls,counts,model): | |
| 836 | + """ | |
| 837 | + Calculate residuals given counts and models, | |
| 838 | + according to algorithm specified by user. | |
| 839 | + Can handle GSkyMap or GNdarray objects | |
| 840 | + :param cls: `~ctools.cscript` | |
| 841 | + cscript class | |
| 842 | + :param counts: `~gammalib.GSkyMap/~gammalib.GNdarray' data counts | |
| 843 | + :param model: `~gammalib.GSkyMap/~gammalib.GNdarray' model counts | |
| 844 | + :return residuals: `~gammalib.GSkyMap/~gammalib.GNdarray' residuals | |
| 845 | + """ | |
| 846 | + # Find type of objects we are manipulating | |
| 847 | + # and set size to iterate later | |
| 848 | + | |
| 849 | + # If GNdarray | |
| 850 | + if counts.classname() == 'GNdarray': | |
| 851 | + nelem = counts.size() | |
| 852 | + elif counts.classname() == 'GSkyMap': | |
| 853 | + nelem = counts.npix() | |
| 854 | + else: | |
| 855 | + msg = 'obsutils.residuals only handles ' \ | |
| 856 | + + 'GNdarray or GSkyMap objects.\n' | |
| 857 | + raise RuntimeError(msg) | |
| 858 | + | |
| 859 | + # Copy counts to initialise residuals | |
| 860 | + residuals = counts.copy() | |
| 861 | + | |
| 862 | + # Get residual map algorithm type | |
| 863 | + algorithm = cls['algorithm'].string() | |
| 864 | + | |
| 865 | + # Subtract | |
| 866 | + if algorithm == 'SUB': | |
| 867 | + residuals -= model | |
| 868 | + | |
| 869 | + # Subtract and divide by model | |
| 870 | + elif algorithm == 'SUBDIV': | |
| 871 | + residuals -= model | |
| 872 | + residuals /= model | |
| 873 | + | |
| 874 | + # Subtract and divide by sqrt of model | |
| 875 | + elif algorithm == 'SUBDIVSQRT': | |
| 876 | + residuals -= model | |
| 877 | + residuals /= model.sqrt() | |
| 878 | + | |
| 879 | + # Calculate significance from Li&Ma | |
| 880 | + elif algorithm == 'SIGNIFICANCE': | |
| 881 | + | |
| 882 | + # Compute sign | |
| 883 | + sign = (residuals - model).sign() | |
| 884 | + | |
| 885 | + # Loop over every bin | |
| 886 | + for i in range(nelem): | |
| 887 | + | |
| 888 | + # If the model value > 0.0 do the computation as normal ... | |
| 889 | + model_val = model[i] | |
| 890 | + if model_val > 0.0: | |
| 891 | + | |
| 892 | + # If the data value is also > 0 then compute the | |
| 893 | + # significance^2 and save it ... | |
| 894 | + data_val = residuals[i] | |
| 895 | + if data_val > 0.0: | |
| 896 | + log_val = math.log(data_val / model_val) | |
| 897 | + residuals[i] = ( | |
| 898 | + data_val * log_val) + model_val - data_val | |
| 899 | + | |
| 900 | + # ... otherwise compute the reduced value of the above | |
| 901 | + # expression. This is necessary to avoid computing log(0). | |
| 902 | + else: | |
| 903 | + residuals[i] = model_val | |
| 904 | + | |
| 905 | + # ... otherwise hard-code the significance to 0 | |
| 906 | + else: | |
| 907 | + residuals[i] = 0.0 | |
| 908 | + | |
| 909 | + # Compute significance map | |
| 910 | + residuals *= 2.0 | |
| 911 | + residuals = residuals.sqrt() | |
| 912 | + residuals = residuals * sign | |
| 913 | + | |
| 914 | + # Raise exception if algorithm is unknown | |
| 915 | + else: | |
| 916 | + raise TypeError('Algorithm "' + algorithm + '" not known') | |
| 917 | + | |
| 918 | + # Return | |
| 919 | + return residuals | |
| 831 | 920 | \ No newline at end of file | ... | ... |