Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Content classification nb (Ch 1) plus question-bank data model #44

Merged
merged 14 commits into from
Jan 19, 2024
3 changes: 2 additions & 1 deletion ci/envs/311-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ dependencies:
- xarray
- rioxarray
- pyarrow
- pooch
- pooch
- anaconda::panel
182 changes: 79 additions & 103 deletions cookbook/question_types.ipynb
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "da2c1dc2-faa0-4086-b5e3-2483a6b8f762",
"metadata": {},
"source": [
"## Example of how to make questions from a JSON file"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee2ffe05-66ec-43f8-b7e6-2db9302dee83",
"metadata": {
"tags": []
},
"id": "8c947305-86db-4aa3-aa4d-b0d92eaffbbb",
"metadata": {},
"outputs": [],
"source": [
"import pathlib\n",
"\n",
"import panel as pn\n",
"\n",
"import coastal_dynamics as cd\n",
"from coastal_dynamics.io import load_questions\n",
"\n",
"# Activate the Panel widget to make the visualizations.\n",
"pn.extension()\n",
"\n",
"# You can save your questions here. Please follow same naming conventions as the notebooks. When converting a Python dictionary\n",
"# with the questions as they are ATM to a JSON file, watch out for trailing comma's. Your code error will warn you. But if you\n",
"# cannot read the JSON file with the function, it's probably related to that.\n",
"QUESTION_DIR = pathlib.Path.cwd().parent / \"notebooks\" / \"questions\"\n",
"question_fp = QUESTION_DIR / \"01_coastal_classification.json\"\n",
"\n",
"# The coastal dynamics package now contains a small utilty function to load the questions from a JSON file\n",
"questions = load_questions(question_fp)\n",
"\n",
"# The QuestionFactory can handle the four question types.\n",
"q1 = cd.QuestionFactory(\n",
" questions[\"Q1-1\"]\n",
").serve() # Here 1-1 refers to notebook 1 question 1.\n",
"q2 = cd.QuestionFactory(questions[\"Q1-2\"]).serve()\n",
"pn.Column(q1, q2)"
]
},
{
"cell_type": "markdown",
"id": "a98d5110-c1df-4ccd-93a2-69c0766e1b14",
"metadata": {},
"source": [
"## Additional examples for all four question types"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bb7b9bac-90cc-45bc-a150-1c8e665ce58a",
"metadata": {},
"outputs": [],
"source": [
"import pathlib\n",
Expand All @@ -15,29 +63,15 @@
"import geoviews.tile_sources as gvts\n",
"import hvplot.pandas\n",
"import hvplot.xarray\n",
"import panel as pn\n",
"import pooch\n",
"import requests\n",
"\n",
"from coastal_dynamics.geometries import geo_bbox\n",
"from coastal_dynamics.questions.factory import QuestionWidgetFactory\n",
"from coastal_dynamics.questions.multiple_choice import MultipleChoiceQuestion\n",
"from coastal_dynamics.questions.multiple_selection import MultipleSelectionQuestion\n",
"from coastal_dynamics.questions.numeric import NumericQuestion\n",
"from coastal_dynamics.questions.text import TextQuestion\n",
"from coastal_dynamics.visualization import DynamicWavePlot\n",
"\n",
"pn.extension()"
]
},
{
"cell_type": "markdown",
"id": "a98d5110-c1df-4ccd-93a2-69c0766e1b14",
"metadata": {},
"source": [
"## Examples for all four question types"
]
},
{
"cell_type": "markdown",
"id": "03cd1328-23c5-4cb4-aedb-5e2ccda3d6ca",
Expand All @@ -53,7 +87,7 @@
"metadata": {},
"outputs": [],
"source": [
"mcq = MultipleChoiceQuestion(\n",
"cd.MultipleChoiceQuestion(\n",
" question_name=\"Q1: Simple Multiple Choice Question\",\n",
" question_text=\"What coastal landform do you typically find in tide-dominated environments?\",\n",
" question_options={\n",
Expand All @@ -63,7 +97,10 @@
" \"d\": \"Mixed sand and gravel beaches\",\n",
" },\n",
" question_answer=\"a\",\n",
" question_feedback={\"correct\": \"Indeed, ...\", \"incorrect\": \"Unfortunately incorrect. Please consder...\"}\n",
" question_feedback={\n",
" \"correct\": \"Indeed, ...\",\n",
" \"incorrect\": \"Unfortunately incorrect. Please consder...\",\n",
" },\n",
").serve()"
]
},
Expand All @@ -82,19 +119,22 @@
"metadata": {},
"outputs": [],
"source": [
"msq = MultipleSelectionQuestion(\n",
"cd.MultipleSelectionQuestion(\n",
" question_name=\"Q1: Simple Multiple Selection Question\",\n",
" question_text=\"Select all morphological systems that are commonly in coastal areas.\",\n",
" question_options={\n",
" \"a\": \"Beaches\",\n",
" \"b\": \"Glaciers\",\n",
" \"c\": \"Estuaries\",\n",
" \"d\": \"Mountains\",\n",
" \"e\": \"Sand\", \n",
" \"f\": \"Mud\", \n",
" \"e\": \"Sand\",\n",
" \"f\": \"Mud\",\n",
" },\n",
" question_answers=[\"a\", \"c\"],\n",
" question_feedback={\"correct\": \"Indeed, ...\", \"incorrect\": \"Unfortunately incorrect. Please consder...\"}\n",
" question_feedback={\n",
" \"correct\": \"Indeed, ...\",\n",
" \"incorrect\": \"Unfortunately incorrect. Please consder...\",\n",
" },\n",
").serve()"
]
},
Expand All @@ -114,13 +154,16 @@
"outputs": [],
"source": [
"kwargs = {\"precision\": 2}\n",
"nq = NumericQuestion(\n",
"cd.NumericQuestion(\n",
" question_name=\"Q3: Simple Numeric Question\",\n",
" question_text=\"What is the PSU of the global ocean?\",\n",
" question_answer=35,\n",
" question_feedback={\"correct\": \"Indeed, ...\", \"incorrect\": \"Unfortunately incorrect. Please consder...\"}, \n",
" question_feedback={\n",
" \"correct\": \"Indeed, ...\",\n",
" \"incorrect\": \"Unfortunately incorrect. Please consder...\",\n",
" },\n",
" **kwargs,\n",
").serve()\n"
").serve()"
]
},
{
Expand All @@ -138,11 +181,14 @@
"metadata": {},
"outputs": [],
"source": [
"TextQuestion(\n",
"cd.TextQuestion(\n",
" question_name=\"Q4: Some simple text question\",\n",
" question_text=\"How do you call the force that generates the tide?\",\n",
" question_answer=\"Gravitational pull\",\n",
" question_feedback={\"correct\": \"Indeed, ...\", \"incorrect\": \"Unfortunately incorrect. Please consder...\"}\n",
" question_feedback={\n",
" \"correct\": \"Indeed, ...\",\n",
" \"incorrect\": \"Unfortunately incorrect. Please consder...\",\n",
" },\n",
").serve().show()"
]
},
Expand Down Expand Up @@ -195,74 +241,6 @@
"pn.Column(wave_plot, base_plot)"
]
},
{
"cell_type": "markdown",
"id": "12f41647-179d-499c-bfd0-b60856307b93",
"metadata": {},
"source": [
"## Make questions from a database (json) that is formatted like below"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "faed7b39",
"metadata": {},
"outputs": [],
"source": [
"## NOTE: Cells below are commented because the factory and json data has to be updated"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fb5cbe03-09f6-4e36-98bb-4304be46a526",
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"import pooch\n",
"\n",
"template_questions_href = pooch.retrieve(\n",
" \"https://coclico.blob.core.windows.net/coastal-dynamics/questions/template.json\",\n",
" known_hash=\"9ef56da50895d243cc5bdb2184f838a33706195522fbb8992767defd6b8d0b96\",\n",
")\n",
"\n",
"with pathlib.Path(template_questions_href).open(\"r\") as f:\n",
" questions = json.loads(f.read())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "22c3f14c-fad5-44de-9b82-d29e30c3c083",
"metadata": {},
"outputs": [],
"source": [
"questions[\"q1\"]"
]
},
{
"cell_type": "markdown",
"id": "1d30b4bf-1feb-4a87-845b-41291c28b8b5",
"metadata": {},
"source": [
"### This is a factory class that builds the quetions based on the question type"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9bfcb690-ea32-41bd-aa64-96a7d987bee9",
"metadata": {},
"outputs": [],
"source": [
"question_data = questions[\"q1\"]\n",
"factory = QuestionWidgetFactory(question_data)\n",
"q1 = factory.create_question_widget().serve() # factory has to be updated because we added a method to add feedback"
]
},
{
"cell_type": "markdown",
"id": "3d26cb47-d55a-40df-a132-0f15af2dc0f6",
Expand All @@ -282,13 +260,11 @@
"\n",
"# Add each question's panel to the main Panel column\n",
"for key, question_data in questions.items():\n",
" question_panel = QuestionWidgetFactory(question_data).create_question_widget().serve()\n",
" question_panel = cd.QuestionFactory(question_data).serve()\n",
" all_questions_panel.append(question_panel)\n",
"\n",
"# Create a wave plot and a base plot\n",
"wave_plot = DynamicWavePlot(\n",
" amplitude_range=(1, 3, 0.5), wavelength_range=(5, 20, 0.1)\n",
")\n",
"wave_plot = DynamicWavePlot(amplitude_range=(1, 3, 0.5), wavelength_range=(5, 20, 0.1))\n",
"base_plot = gvts.EsriImagery(width=900, height=500)\n",
"\n",
"# Combine all components into a single dashboard\n",
Expand Down Expand Up @@ -331,9 +307,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "jl-full",
"display_name": "Python [conda env:coastal]",
"language": "python",
"name": "python3"
"name": "conda-env-coastal-py"
},
"language_info": {
"codemirror_mode": {
Expand Down
Loading