wums 0.1.7__py3-none-any.whl → 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,90 @@
1
+ import wums.fitutils
2
+
3
+ import tensorflow as tf
4
+
5
+ import matplotlib.pyplot as plt
6
+
7
+ import numpy as np
8
+ import hist
9
+ import math
10
+
11
+ np.random.seed(1234)
12
+
13
+ nevt = 100000
14
+
15
+ rgaus = np.random.normal(size=(nevt,))
16
+
17
+ print(rgaus.dtype)
18
+ print(rgaus)
19
+
20
+ axis0 = hist.axis.Regular(100, -5., 5.)
21
+
22
+ htest = hist.Hist(axis0)
23
+ htest.fill(rgaus)
24
+
25
+ print(htest)
26
+
27
+
28
+ quant_cdfvals = tf.constant([0.0, 1e-3, 0.02, 0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 0.95, 0.98, 1.0-1e-3, 1.0], tf.float64)
29
+
30
+ nquants = quant_cdfvals.shape.num_elements()
31
+
32
+ def func_transform_cdf(quantile):
33
+ const_sqrt2 = tf.constant(math.sqrt(2.), quantile.dtype)
34
+ return 0.5*(1. + tf.math.erf(quantile/const_sqrt2))
35
+
36
+ def func_transform_quantile(cdf):
37
+ const_sqrt2 = tf.constant(math.sqrt(2.), cdf.dtype)
38
+ return const_sqrt2*tf.math.erfinv(2*cdf - 1.)
39
+
40
+
41
+
42
+ def func_cdf(xvals, xedges, parms, quant_cdfvals):
43
+ qparms = parms
44
+
45
+ cdf = narf.fitutils.func_cdf_for_quantile_fit(xvals, xedges, qparms, quant_cdfvals, transform = (func_transform_cdf, func_transform_quantile))
46
+
47
+ return cdf
48
+
49
+
50
+ #this is just for plotting
51
+ def func_pdf(h, parms):
52
+ dtype = tf.float64
53
+ xvals = [tf.constant(center, dtype=dtype) for center in h.axes.centers]
54
+ xedges = [tf.constant(edge, dtype=dtype) for edge in h.axes.edges]
55
+
56
+ tfparms = tf.constant(parms)
57
+
58
+ cdf = func_cdf(xvals, xedges, tfparms, quant_cdfvals)
59
+
60
+ pdf = cdf[1:] - cdf[:-1]
61
+ pdf = tf.maximum(pdf, tf.zeros_like(pdf))
62
+
63
+ return pdf
64
+
65
+ nparms = nquants-1
66
+
67
+
68
+ initial_parms = np.array([np.log(1./nparms)]*nparms)
69
+
70
+ res = narf.fitutils.fit_hist(htest, func_cdf, initial_parms, mode="nll_bin_integrated", func_constraint=narf.fitutils.func_constraint_for_quantile_fit, args = (quant_cdfvals,))
71
+
72
+ print(res)
73
+
74
+
75
+ parmvals = res["x"]
76
+
77
+
78
+ pdfvals = func_pdf(htest, parmvals)
79
+ pdfvals *= htest.sum()/np.sum(pdfvals)
80
+
81
+ #
82
+ plot = plt.figure()
83
+ plt.yscale("log")
84
+ htest.plot()
85
+ plt.plot(htest.axes[0].centers, pdfvals)
86
+ # plt.show()
87
+ plot.savefig("test.png")
88
+
89
+
90
+
@@ -0,0 +1,323 @@
1
+ import wums.fitutils
2
+
3
+ import tensorflow as tf
4
+
5
+ import matplotlib.pyplot as plt
6
+
7
+ import numpy as np
8
+ import hist
9
+ import math
10
+
11
+ import onnx
12
+ import tf2onnx
13
+
14
+ np.random.seed(1234)
15
+
16
+ nevt = 20000
17
+
18
+ runiform = np.random.random((nevt,))
19
+ rgaus = np.random.normal(size=(nevt,))
20
+
21
+ data = np.stack([runiform, rgaus], axis=-1)
22
+
23
+ # "pt"-dependent mean and sigma
24
+ data[:,1] = -0.1 + 0.1*data[:,0] + (1. + 0.2*data[:,0])*data[:,1]
25
+
26
+
27
+ # print(rgaus.dtype)
28
+ # print(rgaus)
29
+
30
+ axis0 = hist.axis.Regular(50, 0., 1., name="pt")
31
+ axis1 = hist.axis.Regular(100, -5., 5., name="recoil")
32
+
33
+ htest_data = hist.Hist(axis0, axis1)
34
+ htest_mc = hist.Hist(axis0, axis1)
35
+
36
+ # print("data.shape", data.shape)
37
+ htest_data.fill(data[:nevt//2,0], data[:nevt//2, 1])
38
+ htest_mc.fill(data[nevt//2:,0], data[nevt//2:, 1])
39
+
40
+
41
+
42
+
43
+ quant_cdfvals = tf.constant([0.0, 1e-3, 0.02, 0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 0.95, 0.98, 1.0-1e-3, 1.0], dtype = tf.float64)
44
+ nquants = quant_cdfvals.shape.num_elements()
45
+
46
+ print("nquants", nquants)
47
+
48
+ #cdf is in terms of axis1, so shapes need to be compatible
49
+ quant_cdfvals = quant_cdfvals[None, :]
50
+
51
+
52
+ # get quantiles from histogram, e.g. to help initialize the parameters for the fit (not actually used here)
53
+
54
+ # hist_quantiles, hist_quantile_errs = wums.fitutils.hist_to_quantiles(htest, quant_cdfvals, axis=1)
55
+ #
56
+ # print(hist_quantiles)
57
+ # print(hist_quantile_errs)
58
+ #
59
+ # hist_qparms, hist_qparm_errs = wums.fitutils.quantiles_to_qparms(hist_quantiles, hist_quantile_errs)
60
+ #
61
+ # print(hist_qparms)
62
+ # print(hist_qparm_errs)
63
+
64
+ def parms_to_qparms(xvals, parms):
65
+
66
+ parms_2d = tf.reshape(parms, (-1, 2))
67
+ parms_const = parms_2d[:,0]
68
+ parms_slope = parms_2d[:,1]
69
+
70
+ #cdf is in terms of axis1, so shapes need to be compatible
71
+ parms_const = parms_const[None, :]
72
+ parms_slope = parms_slope[None, :]
73
+
74
+ qparms = parms_const + parms_slope*xvals[0]
75
+
76
+ return qparms
77
+
78
+
79
+ def func_transform_cdf(quantile):
80
+ const_sqrt2 = tf.constant(math.sqrt(2.), quantile.dtype)
81
+ return 0.5*(1. + tf.math.erf(quantile/const_sqrt2))
82
+
83
+ def func_transform_quantile(cdf):
84
+ const_sqrt2 = tf.constant(math.sqrt(2.), cdf.dtype)
85
+ return const_sqrt2*tf.math.erfinv(2.*cdf - 1.)
86
+
87
+ # def func_transform_cdf(quantile):
88
+ # return tf.math.log(quantile/(1.-quantile))
89
+ #
90
+ # def func_transform_quantile(cdf):
91
+ # return tf.math.sigmoid(cdf)
92
+
93
+ def func_cdf(xvals, xedges, parms):
94
+ qparms = parms_to_qparms(xvals, parms)
95
+ # return wums.fitutils.func_cdf_for_quantile_fit(xvals, xedges, qparms, quant_cdfvals, axis=1)
96
+
97
+ return wums.fitutils.func_cdf_for_quantile_fit(xvals, xedges, qparms, quant_cdfvals, axis=1, transform = (func_transform_cdf, func_transform_quantile))
98
+
99
+ def func_constraint(xvals, xedges, parms):
100
+ qparms = parms_to_qparms(xvals, parms)
101
+ return wums.fitutils.func_constraint_for_quantile_fit(xvals, xedges, qparms)
102
+
103
+ #this is just for plotting
104
+ def func_pdf(h, parms):
105
+ dtype = tf.float64
106
+ xvals = [tf.constant(center, dtype=dtype) for center in h.axes.centers]
107
+ xedges = [tf.constant(edge, dtype=dtype) for edge in h.axes.edges]
108
+
109
+ tfparms = tf.constant(parms)
110
+
111
+ cdf = func_cdf(xvals, xedges, tfparms)
112
+
113
+ pdf = cdf[:,1:] - cdf[:,:-1]
114
+ pdf = tf.maximum(pdf, tf.zeros_like(pdf))
115
+
116
+ return pdf
117
+
118
+ nparms = nquants-1
119
+
120
+
121
+ # print("edges", htest.edges)
122
+
123
+ # assert(0)
124
+
125
+ initial_parms_const = np.array([np.log(1./nparms)]*nparms)
126
+ initial_parms_slope = np.zeros_like(initial_parms_const)
127
+
128
+ initial_parms = np.stack([initial_parms_const, initial_parms_slope], axis=-1)
129
+ initial_parms = np.reshape(initial_parms, (-1,))
130
+
131
+ res_data = wums.fitutils.fit_hist(htest_data, func_cdf, initial_parms, mode="nll_bin_integrated", norm_axes=[1])
132
+
133
+ res_mc = wums.fitutils.fit_hist(htest_mc, func_cdf, initial_parms, mode="nll_bin_integrated", norm_axes=[1])
134
+
135
+ print(res_data)
136
+
137
+
138
+ parmvals_data = tf.constant(res_data["x"], tf.float64)
139
+ parmvals_mc = tf.constant(res_mc["x"], tf.float64)
140
+
141
+ hess_data = res_data["hess"]
142
+ hess_mc = res_mc["hess"]
143
+
144
+ def get_scaled_eigenvectors(hess, num_null = 2):
145
+ e,v = np.linalg.eigh(hess)
146
+
147
+ # remove the null eigenvectors
148
+ e = e[None, num_null:]
149
+ v = v[:, num_null:]
150
+
151
+ # scale the eigenvectors
152
+ vscaled = v/np.sqrt(e)
153
+
154
+ return vscaled
155
+
156
+ vscaled_data = tf.constant(get_scaled_eigenvectors(hess_data), tf.float64)
157
+ vscaled_mc = tf.constant(get_scaled_eigenvectors(hess_data), tf.float64)
158
+
159
+ print("vscaled_data.shape", vscaled_data.shape)
160
+
161
+ ut_flat = np.reshape(htest_data.axes.edges[1], (-1,))
162
+ ut_low = tf.constant(ut_flat[0], tf.float64)
163
+ ut_high = tf.constant(ut_flat[-1], tf.float64)
164
+
165
+ def func_cdf_mc(pt, ut):
166
+ pts = tf.reshape(pt, (1,1))
167
+ uts = tf.reshape(ut, (1,1))
168
+
169
+ xvals = [pts, None]
170
+ xedges = [None, uts]
171
+
172
+ parms = parmvals_mc
173
+
174
+ qparms = parms_to_qparms(xvals, parms)
175
+
176
+ ut_axis = 1
177
+
178
+ quants = wums.fitutils.qparms_to_quantiles(qparms, x_low = ut_low, x_high = ut_high, axis = ut_axis)
179
+ spline_edges = xedges[ut_axis]
180
+
181
+ cdfvals = wums.fitutils.pchip_interpolate(quants, quant_cdfvals, spline_edges, axis=ut_axis)
182
+
183
+ return cdfvals
184
+
185
+ def func_cdfinv_data(pt, quant):
186
+ pts = tf.reshape(pt, (1,1))
187
+ quant_outs = tf.reshape(quant, (1,1))
188
+
189
+ xvals = [pts, None]
190
+ xedges = [None, quant_outs]
191
+
192
+ parms = parmvals_data
193
+
194
+ qparms = parms_to_qparms(xvals, parms)
195
+
196
+ ut_axis = 1
197
+
198
+ quants = wums.fitutils.qparms_to_quantiles(qparms, x_low = ut_low, x_high = ut_high, axis = ut_axis)
199
+ spline_edges = xedges[ut_axis]
200
+
201
+ cdfinvvals = wums.fitutils.pchip_interpolate(quant_cdfvals, quants, spline_edges, axis=ut_axis)
202
+
203
+ return cdfinvvals
204
+
205
+ def func_cdfinv_pdf_data(pt, quant):
206
+ with tf.GradientTape() as t:
207
+ t.watch(quant)
208
+ cdfinv = func_cdfinv_data(pt, quant)
209
+ pdfreciprocal = t.gradient(cdfinv, quant)
210
+ pdf = 1./pdfreciprocal
211
+ return cdfinv, pdf
212
+
213
+ scalar_spec = tf.TensorSpec([], tf.float64)
214
+
215
+
216
+ def transform_mc(pt, ut):
217
+ with tf.GradientTape(persistent=True) as t:
218
+ t.watch(parmvals_mc)
219
+ t.watch(parmvals_data)
220
+
221
+ cdf_mc = func_cdf_mc(pt, ut)
222
+ ut_transformed, pdf = func_cdfinv_pdf_data(pt, cdf_mc)
223
+
224
+ ut_transformed = tf.reshape(ut_transformed, [])
225
+ pdf = tf.reshape(pdf, [])
226
+
227
+ pdf_grad_mc = t.gradient(pdf, parmvals_mc)
228
+ pdf_grad_data = t.gradient(pdf, parmvals_data)
229
+
230
+ del t
231
+
232
+ weight_grad_mc = pdf_grad_mc/pdf
233
+ weight_grad_data = pdf_grad_data/pdf
234
+
235
+ weight_grad_mc = weight_grad_mc[None, :]
236
+ weight_grad_data = weight_grad_data[None, :]
237
+
238
+ weight_grad_mc_eig = weight_grad_mc @ vscaled_mc
239
+ weight_grad_data_eig = weight_grad_data @ vscaled_data
240
+
241
+ weight_grad_mc_eig = tf.reshape(weight_grad_mc_eig, [-1])
242
+ weight_grad_data_eig = tf.reshape(weight_grad_data_eig, [-1])
243
+
244
+ weight_grad_eig = tf.concat([weight_grad_mc_eig, weight_grad_data_eig], axis=0)
245
+
246
+ return ut_transformed, weight_grad_eig
247
+ # return ut_transformed
248
+
249
+ @tf.function
250
+ def transform_mc_simple(pt, ut):
251
+ cdf_mc = func_cdf_mc(pt, ut)
252
+ ut_transformed, pdf = func_cdfinv_pdf_data(pt, cdf_mc)
253
+
254
+ ut_transformed = tf.reshape(ut_transformed, [])
255
+
256
+ return ut_transformed
257
+
258
+
259
+
260
+ pt_test = tf.constant(0.2, tf.float64)
261
+ ut_test = tf.constant(1.0, tf.float64)
262
+
263
+ ut, grad = transform_mc(pt_test, ut_test)
264
+ # ut = transform_mc(pt_test, ut_test)
265
+
266
+ print("shapes", ut.shape, grad.shape)
267
+
268
+ print("ut", ut)
269
+ print("grad", grad)
270
+
271
+ input_signature = [scalar_spec, scalar_spec]
272
+
273
+ class TestMod(tf.Module):
274
+
275
+ @tf.function(input_signature = [scalar_spec, scalar_spec])
276
+ def __call__(self, pt, ut):
277
+ return transform_mc(pt, ut)
278
+
279
+ module = TestMod()
280
+ # tf.saved_model.save(module, "test")
281
+
282
+ concrete_function = module.__call__.get_concrete_function()
283
+
284
+ # Convert the model
285
+ converter = tf.lite.TFLiteConverter.from_concrete_functions([concrete_function], module)
286
+
287
+ # converter = tf.lite.TFLiteConverter.from_saved_model("test") # path to the SavedModel directory
288
+ converter.target_spec.supported_ops = [
289
+ tf.lite.OpsSet.TFLITE_BUILTINS, # enable TensorFlow Lite ops.
290
+ tf.lite.OpsSet.SELECT_TF_OPS # enable TensorFlow ops.
291
+ ]
292
+
293
+ tflite_model = converter.convert()
294
+
295
+ # print(tflite_model)
296
+
297
+ # Save the model.
298
+ with open('model.tflite', 'wb') as f:
299
+ f.write(tflite_model)
300
+
301
+
302
+ # onnx_model, _ = tf2onnx.convert.from_function(transform_mc, input_signature)
303
+ # onnx.save(onnx_model, "test.onnx")
304
+
305
+
306
+ parmvals = res_data["x"]
307
+
308
+
309
+ pdfvals = func_pdf(htest_data, parmvals)
310
+ pdfvals *= htest_data.sum()/np.sum(pdfvals)
311
+
312
+
313
+ # hplot = htest[5]
314
+
315
+ plot = plt.figure()
316
+ plt.yscale("log")
317
+ htest_data[5,:].plot()
318
+ plt.plot(htest_data.axes[1].centers, pdfvals[5])
319
+ # plt.show()
320
+ plot.savefig("test.png")
321
+
322
+
323
+
wums/plot_tools.py CHANGED
@@ -683,7 +683,6 @@ def makeStackPlotWithRatio(
683
683
  stackedProcs,
684
684
  histName="nominal",
685
685
  unstacked=None,
686
- fitresult=None,
687
686
  prefit=False,
688
687
  xlabel="",
689
688
  ylabel=None,
@@ -757,11 +756,6 @@ def makeStackPlotWithRatio(
757
756
  if xlim:
758
757
  h = h[complex(0, xlim[0]) : complex(0, xlim[1])]
759
758
 
760
- # If plotting from combine, apply the action to the underlying hist.
761
- # Don't do this for the generic case, as it screws up the ability to make multiple plots
762
- if fitresult:
763
- histInfo[k].hists[histName] = h
764
-
765
759
  if k != "Data":
766
760
  stack.append(h)
767
761
  else:
@@ -803,67 +797,6 @@ def makeStackPlotWithRatio(
803
797
  ratio_axes = None
804
798
  ax2 = None
805
799
 
806
- if fitresult:
807
- import uproot
808
-
809
- combine_result = uproot.open(fitresult)
810
-
811
- fittype = "prefit" if prefit else "postfit"
812
-
813
- # set histograms to prefit/postfit values
814
- for p in to_read:
815
-
816
- hname = f"expproc_{p}_{fittype}" if p != "Data" else "obs"
817
- vals = combine_result[hname].to_hist().values()
818
- if len(histInfo[p].hists[histName].values()) != len(vals):
819
- raise ValueError(
820
- f"The size of the combine histogram ({(vals.shape)}) is not consistent with the xlim or input hist ({histInfo[p].hists[histName].shape})"
821
- )
822
-
823
- histInfo[p].hists[histName].values()[...] = vals
824
- if p == "Data":
825
- histInfo[p].hists[histName].variances()[...] = vals
826
-
827
- # for postfit uncertaity bands
828
- axis = histInfo[to_read[0]].hists[histName].axes[0].edges
829
-
830
- # need to divide by bin width
831
- binwidth = axis[1:] - axis[:-1]
832
- hexp = combine_result[f"expfull_{fittype}"].to_hist()
833
- if hexp.storage_type != hist.storage.Weight:
834
- raise ValueError(
835
- f"Did not find uncertainties in {fittype} hist. Make sure you run combinetf with --computeHistErrors!"
836
- )
837
- nom = hexp.values() / binwidth
838
- std = np.sqrt(hexp.variances()) / binwidth
839
-
840
- hatchstyle = "///"
841
- ax1.fill_between(
842
- axis,
843
- np.append(nom + std, (nom + std)[-1]),
844
- np.append(nom - std, (nom - std)[-1]),
845
- step="post",
846
- facecolor="none",
847
- zorder=2,
848
- hatch=hatchstyle,
849
- edgecolor="k",
850
- linewidth=0.0,
851
- label="Uncertainty",
852
- )
853
-
854
- if add_ratio:
855
- ax2.fill_between(
856
- axis,
857
- np.append((nom + std) / nom, ((nom + std) / nom)[-1]),
858
- np.append((nom - std) / nom, ((nom - std) / nom)[-1]),
859
- step="post",
860
- facecolor="none",
861
- zorder=2,
862
- hatch=hatchstyle,
863
- edgecolor="k",
864
- linewidth=0.0,
865
- )
866
-
867
800
  opts = dict(stack=not no_stack, flow=flow)
868
801
  optsr = opts.copy() # no binwnorm for ratio axis
869
802
  optsr["density"] = density
@@ -994,7 +927,7 @@ def makeStackPlotWithRatio(
994
927
 
995
928
  for i, (proc, style) in enumerate(zip(unstacked, linestyles)):
996
929
  unstack = histInfo[proc].hists[histName]
997
- if not fitresult or proc not in to_read:
930
+ if proc not in to_read:
998
931
  unstack = action(unstack)[select]
999
932
  if proc != "Data":
1000
933
  unstack = unstack * scale
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: wums
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: .
5
5
  Author-email: David Walter <david.walter@cern.ch>, Josh Bendavid <josh.bendavid@cern.ch>, Kenneth Long <kenneth.long@cern.ch>, Jan Eysermans <jan.eysermans@cern.ch>
6
6
  License: MIT
@@ -1,3 +1,5 @@
1
+ scripts/test/testsplinepdf.py,sha256=sXnmDjEXiO0OIHAXLXU4UxTD4_nLwUpoojCecfjyT04,1964
2
+ scripts/test/testsplinepdf2d.py,sha256=vGw9mq67f6aoymefLqv6CqF8teluva4Lx6tpbnC_NGU,8513
1
3
  wums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
4
  wums/boostHistHelpers.py,sha256=mgdPXAgmxriqoOhrhMctyZcfwEOPfV07V27CvGt2sk8,39260
3
5
  wums/fitutils.py,sha256=sPCMJqZGdXvDfc8OxjOB-Bpf45GWHKxmKkDV3SlMUQs,38297
@@ -5,10 +7,10 @@ wums/fitutilsjax.py,sha256=HE1AcIZmI6N_xIHo8OHCPaYkHSnND_B-vI4Gl3vaUmA,2659
5
7
  wums/ioutils.py,sha256=ziyfQQ8CB3Ir2BJKJU3_a7YMF-Jd2nGXKoMQoJ2T8fo,12334
6
8
  wums/logging.py,sha256=L4514Xyq7L1z77Tkh8KE2HX88ZZ06o6SSRyQo96DbC0,4494
7
9
  wums/output_tools.py,sha256=SHcZqXAdqL9AkA57UF0b-R-U4u7rzDgL8Def4E-ulW0,6713
8
- wums/plot_tools.py,sha256=4iPx9Nr9y8c3p4ovy8XOS-xU_w11OyQEjISKkygxqcA,55918
10
+ wums/plot_tools.py,sha256=7GBQAO--wuP8aatkjy-ir1lQWpNrzMc1lSI6zSq3JXE,53502
9
11
  wums/tfutils.py,sha256=9efkkvxH7VtwJN2yBS6_-P9dLKs3CXdxMFdrEBNsna8,2892
10
12
  wums/Templates/index.php,sha256=9EYmfc0ltMqr5oOdA4_BVIHdSbef5aA0ORoRZBEADVw,4348
11
- wums-0.1.7.dist-info/METADATA,sha256=GrQyVuatMvHdallbstH7YdiACEMLIo5isHyugfFawW8,1784
12
- wums-0.1.7.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
13
- wums-0.1.7.dist-info/top_level.txt,sha256=DCE1TVg7ySraosR3kYZkLIZ2w1Pwk2pVTdkqx6E-yRY,5
14
- wums-0.1.7.dist-info/RECORD,,
13
+ wums-0.1.8.dist-info/METADATA,sha256=87fET64UzNDs6swv1-tcJWcuzVE5S3kEuLWOfy1JN6c,1784
14
+ wums-0.1.8.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
15
+ wums-0.1.8.dist-info/top_level.txt,sha256=cGGeFZQ8IwVw-BhgxMCTu5zfkgQelfF1wEFFWGhycds,13
16
+ wums-0.1.8.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ scripts
2
+ wums
@@ -1 +0,0 @@
1
- wums
File without changes