Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Commit

Permalink
Continued adding packaging, including sphinx for readthedocs, and pyp…
Browse files Browse the repository at this point in the history
…i stuff
  • Loading branch information
EdmundGoodman committed Oct 29, 2021
1 parent e52cc18 commit ceb0512
Show file tree
Hide file tree
Showing 9 changed files with 412 additions and 45 deletions.
188 changes: 188 additions & 0 deletions jupylint/Q1.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Before you turn this problem in, make sure everything runs as expected. First, **restart the kernel** (in the menubar, select Kernel$\\rightarrow$Restart) and then **run all cells** (in the menubar, select Cell$\\rightarrow$Run All).\n",
"\n",
"Make sure you fill in any place that says `YOUR CODE HERE` or \"YOUR ANSWER HERE\".\n",
"\n",
"Do not edit or insert code into the test cells as all you insert will be overwritten by the automated testing code."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "99c11bb937160494b316519ed8720bcc",
"grade": false,
"grade_id": "cell-6afd059248794463",
"locked": true,
"schema_version": 3,
"solution": false
}
},
"source": [
"**Question 1**: Fit the Higgs mass - given a `fitter(xvalues, data, init)` function below, write a function `fitfunc(...)` that describes the combined background and signal model to fit the data. Create two pictures: \n",
"\n",
"**(a)** plot the data with cross markers ('+' symbol) and the best fit curve as red line on the first plot and \n",
"\n",
"**(b)** draw the residual ratios with cross markers on the second plot where the residual ratio is defined as the difference between data and fitted model, divided by data for every data point.\n",
"\n",
"The fit function is composed of a background model with 3 parameters $$b(m)=A\\,\\exp{}\\left( b_{1}\\,(m - 105.5)+b_{2}\\,(m-105.5)^{2}\\right).$$ The signal is added to the background and its model is $$s(m) = \\frac{R}{\\sigma\\sqrt{2\\,\\pi}}\\,\\exp{}\\left(-\\frac{(m-\\mu{})^{2}}{2\\sigma^{2}}\\right),$$ featuring another 3 parameters for a total of six parameters to fit.\n",
"\n",
"A set of 6 initial values for the fit are given. You could draw the data and the initial values, inserted into your function, on the same plot and convince yourself that these are close to the best in order to check your function.\n",
"\n",
"The xvalues represent masses (in GeV units) of potential particles decaying into two photons in the ATLAS detector at CERN. Any peak would correspond to a real particle having decayed while a smooth background represents chance coincidences or simply noise. The peak to fit at a bit above 125 GeV led to the announcement of the discovery of the Higgs particle at CERN in 2012. The data itself is read off a histogram (in counts) hence the xvalues really are bin centres at the mass values as indicated."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "bd140020f5001d16d02ea5b445805050",
"grade": false,
"grade_id": "Q1Code",
"locked": false,
"schema_version": 3,
"solution": true
}
},
"outputs": [],
"source": [
"def fitfunc(xvalues, mu, sigma, R, A, b1, b2):\n",
" pass\n",
"\n",
"# Given\n",
"# write the fitfunc function above(!) this since it is being used below.\n",
"def fitter(xval, yval, initial):\n",
" ''' function to fit the given data using a 'fitfunc' TBD.\n",
" The curve_fit function is called. Only the best fit values\n",
" are returned to be utilized in a main script.\n",
" '''\n",
" best, _ = curve_fit(fitfunc, xval, yval, p0=initial)\n",
" return best\n",
"\n",
"# Use functions with script below for plotting parts (a) and (b)\n",
"# start value parameter definitions, see equations for s(m) and b(m).\n",
"# init[0] = mu\n",
"# init[1] = sigma\n",
"# init[2] = R\n",
"# init[3] = A\n",
"# init[4] = b1\n",
"# init[5] = b2\n",
"init = (125.8, 1.4, 470.0, 5000.0, -0.04, -1.5e-4)\n",
"xvalues = np.arange(start=105.5, stop=160.5, step=1)\n",
"data = np.array([4780, 4440, 4205, 4150, 3920, 3890, 3590, 3460, 3300, 3200, 3000,\n",
" 2950, 2830, 2700, 2620, 2610, 2510, 2280, 2330, 2345, 2300, 2190,\n",
" 2080, 1990, 1840, 1830, 1730, 1680, 1620, 1600, 1540, 1505, 1450,\n",
" 1410, 1380, 1380, 1250, 1230, 1220, 1110, 1110, 1080, 1055, 1050,\n",
" 940, 920, 950, 880, 870, 850, 800, 820, 810, 770, 760])\n",
"# YOUR CODE HERE"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "668d0b7c46c41a0cc44c2c556f3fceeb",
"grade": true,
"grade_id": "Q1testA",
"locked": true,
"points": 1,
"schema_version": 3,
"solution": false
}
},
"outputs": [],
"source": [
"# Test cell\n",
"val = fitfunc(xvalues, init[0], init[1], init[2], init[3], init[4], init[5])\n",
"assert (val[1]>4800 and val[1]<4805), 'fitfunc wrong or initial values changed'\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "671de141388de3893c2d65144d466cb9",
"grade": true,
"grade_id": "Q1testB",
"locked": true,
"points": 2,
"schema_version": 3,
"solution": false
}
},
"outputs": [],
"source": [
"# Test cell\n",
"bf = fitter(xvalues, data, init)\n",
"assert (bf[0]<126.0 and bf[0]>125.9), 'bad fit'\n",
"assert (bf[1]<1.55 and bf[1]>1.5), 'bad fit'"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "fe6d5ae4a5f9919c1aa047d4c10e51d4",
"grade": false,
"grade_id": "cell-8022607b6d0c07f1",
"locked": true,
"schema_version": 3,
"solution": false
}
},
"source": [
"### Tests - 3 marks; Style - 1 mark; Plots - 3 marks"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
2 changes: 2 additions & 0 deletions jupylint/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from .jupylint import Jupylint
99 changes: 54 additions & 45 deletions jupylint/jupylint.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,70 @@
"""A simple tool to extract python code from a Jupyter notebook, and then run
pylint on it for static analysis."""

import argparse

from argparse import ArgumentParser
from os import system, remove
from json import load

CELL_SEPARATOR = "# " + ("=" * 78) + "\n"
DEFAULT_IN_FILE = "Q1.ipynb"
DEFAULT_OUT_FILE = "out.py"
class Jupylint:
"""The tool to extract from Jupyter notebooks and run pylint"""
CELL_SEPARATOR = "# " + ("=" * 78) + "\n"
DEFAULT_IN_FILE = "Q1.ipynb"
DEFAULT_OUT_FILE = "out.py"

def extract_content(content, out_file_name="out.py"):
"""Extract the code blocks from the json and write it out to a file"""
with open(out_file_name, "w+", encoding='utf-8') as out_file:
for cell in content:
if cell["cell_type"] == "code":
out_file.write(CELL_SEPARATOR)
for line in cell["source"]:
out_file.write(line)
out_file.write("\n\n")
@staticmethod
def extract_content(content, out_file_name="out.py"):
"""Extract the code blocks from the json and write it out to a file"""
with open(out_file_name, "w+", encoding='utf-8') as out_file:
for cell in content:
if cell["cell_type"] == "code":
out_file.write(Jupylint.CELL_SEPARATOR)
for line in cell["source"]:
out_file.write(line)
out_file.write("\n\n")

@staticmethod
def get_json_contents(in_file_name):
"""Extract the json contents from the Jupyter file"""
content = ""
with open(in_file_name, "r", encoding='utf-8') as in_file:
content = load(in_file)

def get_json_contents(in_file_name):
"""Extract the json contents from the Jupyter file"""
content = ""
with open(in_file_name, "r", encoding='utf-8') as in_file:
content = load(in_file)
if content["nbformat"] >= 4:
return content["cells"]
return content["worksheets"][0]["cells"]

if content["nbformat"] >= 4:
return content["cells"]
return content["worksheets"][0]["cells"]
@staticmethod
def run():
"""Run the tool, running pylint on the code within a specified Jupyter
notebook"""

# Parse keyword arguments
parser = ArgumentParser(description="""A simple tool to extract
python code from a Jupyter notebook, and then run pylint on it for static
analysis.""")

if __name__ == "__main__":
# Parse keyword arguments
parser = argparse.ArgumentParser(description="""A simple tool to extract
python code from a Jupyter notebook, and then run pylint on it for static
analysis.""")
parser.add_argument('in_file_name', metavar='input file name', type=str,
nargs='?', default=Jupylint.DEFAULT_IN_FILE,
help='the name of the Jupyter notebook file to extract the code from')
parser.add_argument('out_file_name', metavar='output file name', type=str,
nargs='?', default=Jupylint.DEFAULT_OUT_FILE,
help='the name of the output file to write the extracted code to')
parser.add_argument('-k', '--keep', dest='save_file', action='store_false',
help='a boolean specifying whether to keep the extracted python file')
args = parser.parse_args()
print(args)

parser.add_argument('in_file_name', metavar='input file name', type=str,
nargs='?', default=DEFAULT_IN_FILE,
help='the name of the Jupyter notebook file to extract the code from')
parser.add_argument('out_file_name', metavar='output file name', type=str,
nargs='?', default=DEFAULT_OUT_FILE,
help='the name of the output file to write the extracted code to')
parser.add_argument('-k', '--keep', dest='save_file', action='store_false',
help='a boolean specifying whether to keep the extracted python file')
args = parser.parse_args()
print(args)
# Call the extract and write out the code contents
json_contents = Jupylint.get_json_contents(args.in_file_name)
Jupylint.extract_content(json_contents)

# Call the extract and write out the code contents
json_contents = get_json_contents(args.in_file_name)
extract_content(json_contents)
# Run pylint
system(f"pylint {args.out_file_name}")

# Run pylint
system(f"pylint {args.out_file_name}")
# Clean up
if not args.save_file:
remove(args.out_file_name)

# Clean up
if not args.save_file:
remove(args.out_file_name)

if __name__ == "__main__":
Jupylint.run()
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[metadata]
description-file = README.md
30 changes: 30 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from setuptools import setup, find_packages


with open("README.md", "r") as fh:
long_description = fh.read()

setup(
name = 'jupyliny',
version = '0.1.0',
license='MIT',
description = 'A tool to run pylint on Jupyter notebooks',
long_description=long_description,
long_description_content_type="text/markdown",
author = 'Edmund Goodman',
author_email = 'egoodman3141@gmail.com',
url = 'https://github.com/EdmundGoodman/Jupyter_Pylinter',
download_url = 'https://github.com/EdmundGoodman/Jupyter_Pylinter/archive/refs/tags/v0.1.0.tar.gz',
packages=find_packages(),
keywords = ['Jupyter', 'Pylint', 'linter'],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
)
18 changes: 18 additions & 0 deletions source/autodoc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.. role:: raw-html(raw)
:format: html


Interface
=========

.. automodule:: jupylint


Jupylint object
---------------

.. autoclass:: Jupylint
:members:
:private-members:
:special-members:
:show-inheritance:
Loading

0 comments on commit ceb0512

Please sign in to comment.