| import gradio as gr |
| import pandas as pd |
|
|
| |
| ROASTER_URL = "hf://datasets/Ichlibitiche/roasterdb-specialty-coffee-sample/roasterdb_sample.csv" |
| FLORA_URL = "hf://datasets/Ichlibitiche/floradb-houseplants-care-sample/floradb_sample.csv" |
| SUPP_URL = "hf://datasets/Ichlibitiche/suppdb-supplements-sample/suppdb_sample.csv" |
|
|
| WHISKY_BASE = "hf://datasets/Ichlibitiche/whiskydb-fine-spirits-sample/" |
|
|
| r_df = pd.read_csv(ROASTER_URL) |
| f_df = pd.read_csv(FLORA_URL) |
| s_df = pd.read_csv(SUPP_URL) |
| w_df = pd.read_csv(WHISKY_BASE + "spirits.csv") |
| w_dist_df = pd.read_csv(WHISKY_BASE + "distilleries.csv") |
| w_casks_df = pd.read_csv(WHISKY_BASE + "casks_taxonomy.csv") |
| w_flavors_df = pd.read_csv(WHISKY_BASE + "flavors_taxonomy.csv") |
|
|
|
|
| def choices(df, col): |
| vals = df[col].dropna().astype(str) |
| return ["All"] + sorted(v for v in vals.unique() if v.strip() and v != "Unknown") |
|
|
|
|
| |
| R_COLS = { |
| "source_roaster": "Roaster", |
| "title": "Coffee", |
| "origin_country": "Origin", |
| "process_method": "Process", |
| "roast_level": "Roast", |
| "weight_grams": "Weight (g)", |
| "price_value": "Price (USD)", |
| "tasting_notes_sca_nodes": "SCA Flavor Notes", |
| "source_url": "Source URL", |
| } |
| R_PRICE_MAX = float(r_df["price_value"].max()) |
|
|
| def r_explore(roaster, country, process, roast, flavor, max_price): |
| d = r_df |
| if roaster != "All": |
| d = d[d["source_roaster"] == roaster] |
| if country != "All": |
| d = d[d["origin_country"] == country] |
| if process != "All": |
| d = d[d["process_method"] == process] |
| if roast != "All": |
| d = d[d["roast_level"] == roast] |
| if flavor and flavor.strip(): |
| d = d[d["tasting_notes_sca_nodes"].fillna("").str.contains(flavor.strip(), case=False, regex=False)] |
| if max_price < R_PRICE_MAX: |
| d = d[d["price_value"].fillna(R_PRICE_MAX + 1) <= max_price] |
| summary = ( |
| f"**{len(d)} coffees** from **{d['source_roaster'].nunique()} roasters** match β " |
| f"out of {len(r_df)} in the free sample. The full RoasterDB has **8,000+ products from 280+ roasters**." |
| ) |
| return summary, d[list(R_COLS)].rename(columns=R_COLS).sort_values("Price (USD)") |
|
|
|
|
| |
| F_COLS = { |
| "common_name": "Common Name", |
| "scientific_name": "Scientific Name", |
| "family": "Family", |
| "light_requirement_level": "Light", |
| "min_lux": "Min Lux", |
| "max_lux": "Max Lux", |
| "watering_frequency_days": "Water Every (days)", |
| "min_temp_celsius": "Min Β°C", |
| "max_temp_celsius": "Max Β°C", |
| "is_toxic_to_dogs": "Toxic: Dogs", |
| "is_toxic_to_cats": "Toxic: Cats", |
| "toxicity_status": "Toxicity Source", |
| "care_confidence": "Care Confidence", |
| "gbif_source_url": "GBIF Source", |
| } |
| F_PET_FILTERS = [ |
| "All", |
| "Verified safe for dogs", |
| "Verified safe for cats", |
| "Toxic to dogs or cats", |
| "Toxicity unknown", |
| ] |
|
|
| def f_explore(name_query, family, light, confidence, pet_filter): |
| d = f_df |
| if name_query and name_query.strip(): |
| q = name_query.strip() |
| hit = ( |
| d["common_name"].fillna("").str.contains(q, case=False, regex=False) |
| | d["scientific_name"].fillna("").str.contains(q, case=False, regex=False) |
| ) |
| d = d[hit] |
| if family != "All": |
| d = d[d["family"] == family] |
| if light != "All": |
| d = d[d["light_requirement_level"] == light] |
| if confidence != "All": |
| d = d[d["care_confidence"] == confidence] |
| |
| if pet_filter == "Verified safe for dogs": |
| d = d[(d["is_toxic_to_dogs"] == 0) & (d["toxicity_status"] != "unknown")] |
| elif pet_filter == "Verified safe for cats": |
| d = d[(d["is_toxic_to_cats"] == 0) & (d["toxicity_status"] != "unknown")] |
| elif pet_filter == "Toxic to dogs or cats": |
| d = d[(d["is_toxic_to_dogs"] == 1) | (d["is_toxic_to_cats"] == 1)] |
| elif pet_filter == "Toxicity unknown": |
| d = d[d["toxicity_status"] == "unknown"] |
| summary = ( |
| f"**{len(d)} plants** across **{d['family'].nunique()} families** match β " |
| f"out of {len(f_df)} in the free sample. " |
| f"The full FloraDB has **270 care plants + 891 ASPCA toxicity records + a 20,000+ species GBIF index**." |
| ) |
| return summary, d[list(F_COLS)].rename(columns=F_COLS) |
|
|
|
|
| |
| S_COLS = { |
| "brand": "Brand", |
| "product_name": "Product", |
| "form_type": "Form", |
| "ingredient": "Ingredient", |
| "ingredient_form": "Ingredient Form", |
| "ingredient_category": "Category", |
| "amount_per_serving_mg": "Dose (mg/serving)", |
| "is_proprietary_blend": "Hidden in Blend", |
| "recommended_daily_mg": "NIH RDA (mg)", |
| "upper_safety_limit_mg": "Upper Limit (mg)", |
| "molecular_formula": "Formula", |
| "source_url": "NIH DSLD Label", |
| } |
| S_BLEND_FILTERS = [ |
| "All", |
| "Disclosed doses only", |
| "Proprietary-blend (hidden dose) only", |
| ] |
|
|
| def s_explore(ingredient_query, brand, category, form, blend_filter): |
| d = s_df |
| if ingredient_query and ingredient_query.strip(): |
| q = ingredient_query.strip() |
| hit = ( |
| d["ingredient"].fillna("").str.contains(q, case=False, regex=False) |
| | d["product_name"].fillna("").str.contains(q, case=False, regex=False) |
| ) |
| d = d[hit] |
| if brand != "All": |
| d = d[d["brand"] == brand] |
| if category != "All": |
| d = d[d["ingredient_category"] == category] |
| if form != "All": |
| d = d[d["form_type"] == form] |
| if blend_filter == "Disclosed doses only": |
| d = d[d["is_proprietary_blend"] == 0] |
| elif blend_filter == "Proprietary-blend (hidden dose) only": |
| d = d[d["is_proprietary_blend"] == 1] |
| summary = ( |
| f"**{len(d)} ingredient records** across **{d['product_id'].nunique()} products** " |
| f"from **{d['brand'].nunique()} brands** match β out of {len(s_df)} records in the free sample. " |
| f"The full SuppDB has **115,000+ ingredient records across 17,000+ products**." |
| ) |
| return summary, d[list(S_COLS)].rename(columns=S_COLS) |
|
|
|
|
| |
| W_COLS = { |
| "name": "Spirit", |
| "type": "Type", |
| "age": "Age (years)", |
| "abv": "ABV %", |
| "volume_ml": "Volume (ml)", |
| "source_name": "Source", |
| "source_url": "Source URL", |
| } |
|
|
| def w_explore(query, spirit_type): |
| d = w_df |
| if query and query.strip(): |
| d = d[d["name"].fillna("").str.contains(query.strip(), case=False, regex=False)] |
| if spirit_type != "All": |
| d = d[d["type"] == spirit_type] |
| summary = ( |
| f"**{len(d)} spirits** match β out of {len(w_df)} in the free sample. " |
| f"The full WhiskyDB has **1,290+ spirits, 3,200+ distilleries & 20,000+ monthly auction-price benchmarks (2005 β today)**." |
| ) |
| return summary, d[list(W_COLS)].rename(columns=W_COLS) |
|
|
|
|
| |
| with gr.Blocks(title="Dataset Sample Explorers") as demo: |
| gr.Markdown("# ποΈ Dataset Sample Explorers") |
| gr.Markdown("""Interactive explorers for the **free samples** of four curated commercial datasets. Every record carries a source URL so any fact can be re-verified. Full datasets are available at each official portal.""") |
|
|
| with gr.Tab("β RoasterDB β Specialty Coffee"): |
| gr.Markdown(f"""**{len(r_df)} verified coffees from {r_df['source_roaster'].nunique()} artisan roasters**, tasting notes normalized to the **SCA Flavor Wheel**. Full dataset: **8,000+ products, 280+ roasters** β [roasterdb.net](https://specialty-coffee-roasterdb.pages.dev) Β· [π€ sample dataset](https://huggingface.co/datasets/Ichlibitiche/roasterdb-specialty-coffee-sample) Β· [π Kaggle](https://www.kaggle.com/datasets/ahtiticheamine/roasterdb-specialty-coffee-sample) Β· [π Apify scraper](https://apify.com/dataengineered/specialty-coffee-roaster-scraper)""") |
| with gr.Row(): |
| r_roaster = gr.Dropdown(choices=choices(r_df, "source_roaster"), value="All", label="Roaster") |
| r_country = gr.Dropdown(choices=choices(r_df, "origin_country"), value="All", label="Origin Country") |
| r_process = gr.Dropdown(choices=choices(r_df, "process_method"), value="All", label="Process Method") |
| r_roast = gr.Dropdown(choices=choices(r_df, "roast_level"), value="All", label="Roast Level") |
| with gr.Row(): |
| r_flavor = gr.Textbox(label="SCA Flavor Search", placeholder="e.g. Berry, Chocolate, Floral, Peach...") |
| r_price = gr.Slider(minimum=0, maximum=R_PRICE_MAX, value=R_PRICE_MAX, step=1, label="Max Price (USD)") |
| r_btn = gr.Button("Explore Coffees", variant="primary") |
| r_text = gr.Markdown() |
| r_table = gr.Dataframe(label="Matching Coffees", wrap=True) |
| r_inputs = [r_roaster, r_country, r_process, r_roast, r_flavor, r_price] |
| r_btn.click(fn=r_explore, inputs=r_inputs, outputs=[r_text, r_table]) |
| demo.load(fn=r_explore, inputs=r_inputs, outputs=[r_text, r_table]) |
|
|
| with gr.Tab("πΏ FloraDB β Houseplants & Pet Toxicity"): |
| gr.Markdown(f"""**{len(f_df)} houseplants from {f_df['family'].nunique()} botanical families** β care as **quantitative metrics** (Lux, watering days, Β°C) with **ASPCA pet toxicity** on GBIF-verified names. Full dataset: **270 care plants + 891 toxicity records + 20,000+ species index** β [floradb](https://houseplants-botanical-floradb.pages.dev) Β· [π€ sample dataset](https://huggingface.co/datasets/Ichlibitiche/floradb-houseplants-care-sample) Β· [π Kaggle](https://www.kaggle.com/datasets/ahtiticheamine/floradb-houseplants-care-sample) Β· [π Apify lookup](https://apify.com/dataengineered/houseplant-care-toxicity-lookup)""") |
| with gr.Row(): |
| f_name = gr.Textbox(label="Plant Search", placeholder="e.g. Monstera, Pothos, Ficus...") |
| f_family = gr.Dropdown(choices=choices(f_df, "family"), value="All", label="Botanical Family") |
| f_light = gr.Dropdown(choices=choices(f_df, "light_requirement_level"), value="All", label="Light Requirement") |
| with gr.Row(): |
| f_conf = gr.Dropdown(choices=choices(f_df, "care_confidence"), value="All", label="Care Confidence") |
| f_pet = gr.Dropdown(choices=F_PET_FILTERS, value="All", label="Pet Safety (ASPCA-based, conservative)") |
| f_btn = gr.Button("Explore Plants", variant="primary") |
| f_text = gr.Markdown() |
| f_table = gr.Dataframe(label="Matching Plants", wrap=True) |
| f_inputs = [f_name, f_family, f_light, f_conf, f_pet] |
| f_btn.click(fn=f_explore, inputs=f_inputs, outputs=[f_text, f_table]) |
| demo.load(fn=f_explore, inputs=f_inputs, outputs=[f_text, f_table]) |
|
|
| with gr.Tab("π SuppDB β Supplements & Nootropics"): |
| gr.Markdown(f"""**{len(s_df)} active-ingredient records from {s_df['product_id'].nunique()} real supplement products ({s_df['brand'].nunique()} brands)** β NIH DSLD labels with **mg-normalized doses**, **proprietary-blend transparency**, and **PubChem chemistry**. Full dataset: **17,000+ products, 115,000+ ingredient records** β [suppdb.net](https://supplements-nootropics-suppdb.pages.dev) Β· [π€ sample dataset](https://huggingface.co/datasets/Ichlibitiche/suppdb-supplements-sample) Β· [π Kaggle](https://www.kaggle.com/datasets/ahtiticheamine/suppdb-supplements-sample)""") |
| with gr.Row(): |
| s_query = gr.Textbox(label="Ingredient / Product Search", placeholder="e.g. Magnesium, Ashwagandha, Vitamin D...") |
| s_brand = gr.Dropdown(choices=choices(s_df, "brand"), value="All", label="Brand") |
| with gr.Row(): |
| s_category = gr.Dropdown(choices=choices(s_df, "ingredient_category"), value="All", label="Ingredient Category") |
| s_form = gr.Dropdown(choices=choices(s_df, "form_type"), value="All", label="Product Form") |
| s_blend = gr.Dropdown(choices=S_BLEND_FILTERS, value="All", label="Proprietary-Blend Transparency") |
| s_btn = gr.Button("Explore Supplements", variant="primary") |
| s_text = gr.Markdown() |
| s_table = gr.Dataframe(label="Matching Ingredient Records", wrap=True) |
| s_inputs = [s_query, s_brand, s_category, s_form, s_blend] |
| s_btn.click(fn=s_explore, inputs=s_inputs, outputs=[s_text, s_table]) |
| demo.load(fn=s_explore, inputs=s_inputs, outputs=[s_text, s_table]) |
|
|
| with gr.Tab("π₯ WhiskyDB β Fine Spirits"): |
| gr.Markdown(f"""**{len(w_df)} spirits + {len(w_dist_df)} distilleries**, provenance-tracked from open public sources, with **fully open cask & flavor taxonomies** (CC BY 4.0). Full dataset: **1,290+ spirits, 3,200+ distilleries, 20,000+ monthly auction-price benchmarks (Nov 2005 β today)** β [π€ sample dataset](https://huggingface.co/datasets/Ichlibitiche/whiskydb-fine-spirits-sample) Β· [π GitHub](https://github.com/WhiskyyDB/whisky-database) Β· [π§ get the full dataset](mailto:whiskeydn.kite979@simplelogin.com)""") |
| with gr.Row(): |
| w_query = gr.Textbox(label="Spirit Search", placeholder="e.g. Lagavulin, Eagle Rare, Yamazaki...") |
| w_type = gr.Dropdown(choices=choices(w_df, "type"), value="All", label="Spirit Type") |
| w_btn = gr.Button("Explore Spirits", variant="primary") |
| w_text = gr.Markdown() |
| w_table = gr.Dataframe(label="Matching Spirits", wrap=True) |
| w_inputs = [w_query, w_type] |
| w_btn.click(fn=w_explore, inputs=w_inputs, outputs=[w_text, w_table]) |
| demo.load(fn=w_explore, inputs=w_inputs, outputs=[w_text, w_table]) |
| with gr.Accordion(f"π Sample Distilleries ({len(w_dist_df)})", open=False): |
| gr.Dataframe(value=w_dist_df.rename(columns={"name": "Distillery", "country": "Country", "region": "Region", "source_url": "Source URL"})[["Distillery", "Country", "Region", "Source URL"]], wrap=True) |
| with gr.Accordion(f"π’οΈ Open Cask Taxonomy ({len(w_casks_df)} styles, CC BY 4.0)", open=False): |
| gr.Dataframe(value=w_casks_df, wrap=True) |
| with gr.Accordion(f"π Open Flavor Taxonomy ({len(w_flavors_df)} descriptors, CC BY 4.0)", open=False): |
| gr.Dataframe(value=w_flavors_df, wrap=True) |
|
|
| gr.Markdown("""--- |
| *Sample data CC BY-NC 4.0 (per-dataset attribution on each tab); WhiskyDB taxonomies CC BY 4.0. FloraDB toxicity data is informational, not veterinary advice; SuppDB is factual label data, not medical advice. Full datasets commercially licensed at each portal. Sister project: [π¬ INCIDB Skincare Dupe Finder](https://huggingface.co/spaces/Ichlibitiche/incidb-skincare-dupe-finder).*""") |
|
|
| demo.launch() |
|
|