Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import streamlit as st
- import requests
- import matplotlib.pyplot as plt
- # Edamam API credentials
- EDAMAM_APP_ID = 'b43bfd1e'
- EDAMAM_APP_KEY = '52c88b2f791a5ddecbecf76a970d8a13'
- def get_recipes(food, calories_max, include_ingredient=None, exclude_ingredient=None, num_recipes=1):
- # The url with the inserted API credentials
- url = f"https://api.edamam.com/search?q={food}&app_id={EDAMAM_APP_ID}&app_key={EDAMAM_APP_KEY}"
- # get the response back and save the outputed information in a list data
- response = requests.get(url)
- data = response.json()
- # If nothing was found return none
- if 'hits' not in data or not data['hits']:
- return None
- # Filter recipes based on criteria given by user
- recipes = data['hits']
- filtered_recipes = []
- # go over all recipes which match criteria
- for hit in recipes:
- recipe = hit['recipe']
- ingredients = recipe['ingredientLines']
- calories = recipe['calories']
- # Exclude recipes with calories greater than max_calories
- if calories > calories_max:
- continue
- # search if any words mentioned in include/exclude are part of the ingredients (even subwords or lower/uppercase)
- if include_ingredient and not any(
- include_ingredient.lower() in ingredient.lower() for ingredient in ingredients):
- # if not, we go into the next for loop iteration
- continue
- if exclude_ingredient and any(exclude_ingredient.lower() in ingredient.lower() for ingredient in ingredients):
- continue
- # append them to the list of recipes we want
- filtered_recipes.append(recipe)
- # if the list is empty, we return none
- if not filtered_recipes:
- return None
- return filtered_recipes[:num_recipes]
- def plot_nutrition(recipe):
- # define the advised daily amount of each ingredient
- daily_sugar = 25 # Example daily sugar amount in grams
- daily_salt = 6 # Example daily salt amount in grams
- daily_energy = 2000 # Example daily calorie amount in kcal
- # define a standard font size for better design
- fontsize = 16
- nutrients = recipe['totalNutrients']
- # Get sugar, salt, and calorie data
- sugar = nutrients.get('SUGAR', {'label': 'Sugar', 'quantity': 0})
- salt = nutrients.get('SUGAR', {'label': 'Salt', 'quantity': 0})
- energy = nutrients.get('ENERC_KCAL', {'label': 'Energy', 'quantity': 0})
- # Calculate percentage of suggested daily amounts
- sugar_percent = (sugar['quantity'] / daily_sugar) * 100
- salt_percent = (salt['quantity'] / daily_salt) * 100
- energy_percent = (energy['quantity'] / daily_energy) * 100
- banner_color = '#FF6347' # Red color of the banner
- fig, axes = plt.subplots(1, 3, figsize=(20, 6))
- plt.style.use('ggplot')
- # The max is needed such that the counterpart is not negative if the amount is bigger than the suggested daily amount.
- # Sugar Pie Chart
- axes[0].pie([sugar_percent, max(100 - sugar_percent, 0)], labels=['', 'Remaining'], colors=[banner_color, '#20B2AA'],
- autopct='%1.1f%%',
- shadow=True, startangle=90, textprops={'fontsize': fontsize}, wedgeprops={'edgecolor': 'black'})
- axes[0].axis('equal')
- axes[0].set_title('Sugar (' + str(round(sugar['quantity'])) + "g/" + str(round(sugar_percent)) + "%)",
- fontweight='bold', fontsize=fontsize, color='black')
- # Salt Pie Chart
- axes[1].pie([salt_percent, max(0, 100 - salt_percent)], labels=['', 'Remaining'],
- colors=[banner_color, '#20B2AA'], autopct='%1.1f%%',
- shadow=True, startangle=90, textprops={'fontsize': fontsize}, wedgeprops={'edgecolor': 'black'})
- axes[1].axis('equal')
- axes[1].set_title('Salt (' + str(round(salt['quantity'])) + "g/" + str(round(salt_percent)) + "%)",
- fontweight='bold', fontsize=fontsize, color='black')
- # Calorie Pie Chart
- axes[2].pie([energy_percent, max(0, 100 - energy_percent)], labels=['', 'Remaining'],
- colors=[banner_color, '#20B2AA'], autopct='%1.1f%%',
- shadow=True, startangle=90, textprops={'fontsize': fontsize}, wedgeprops={'edgecolor': 'black'})
- axes[2].axis('equal')
- axes[2].set_title('Calories (' + str(round(energy['quantity'])) + "/" + str(round(energy_percent)) + "%)",
- fontweight='bold', fontsize=fontsize, color='black')
- # Plot the graphs
- st.pyplot(fig)
- # Streamlit main function
- def main():
- # Streamlit page title and styling
- st.title("Welcome to DailyCalories!")
- # define different markdown classes for a better more standardized design
- st.markdown(
- """
- <style>
- body {
- background-color: #f0f0f0;
- color: #333333;
- font-family: Arial, sans-serif;
- line-height: 1.6;
- }
- .container {
- max-width: 800px;
- margin: 0 auto;
- padding: 20px;
- }
- .header {
- background-color: #007bff;
- color: white;
- padding: 20px;
- border-radius: 5px;
- }
- .subheader {
- font-size: 20px;
- font-weight: bold;
- margin-bottom: 20px;
- }
- .input {
- margin-bottom: 20px;
- }
- .button {
- background-color: #FF6347; /* Changed button color to red */
- color: white;
- border: none;
- padding: 10px 20px;
- border-radius: 5px;
- cursor: pointer;
- font-size: 16px;
- }
- .button:hover {
- background-color: #D32F2F; /* Darker red on hover */
- }
- .image {
- max-width: 100%;
- margin-bottom: 20px;
- border-radius: 5px;
- }
- .share-banner {
- background-color: #FF6347; /* Red color for the share banner */
- color: white;
- padding: 10px;
- text-align: center;
- margin-top: 20px;
- border-radius: 5px;
- }
- .share-banner a {
- color: white;
- margin: 0 10px;
- font-size: 20px;
- }
- </style>
- """,
- # somehow otherwise we get bugs
- unsafe_allow_html=True
- )
- # Streamlit input fields for user input
- st.write("""Find the best recipes tailored to your liking""")
- food_type = st.text_input("Enter a Food Type:", "Pasta")
- max_calories = st.number_input("Enter Maximum Calories:", min_value=0, step=100, value=1500)
- include_ingredient = st.text_input("Include Ingredient (optional):")
- exclude_ingredient = st.text_input("Exclude Ingredient (optional):")
- num_recipes = st.number_input("Number of Recipes to Show:", min_value=1, step=1, value=5)
- # Button to trigger recipe search
- if st.button("Find Recipes", key='find_recipes_button'):
- # Call the get_recipes function to fetch recipes
- recipes = get_recipes(food_type, max_calories, include_ingredient, exclude_ingredient, num_recipes)
- # Only do it if recipes is not none, if it were, it means that we found no recipes
- if recipes:
- # Loop over all recipes and put them into an expander
- for recipe in recipes:
- with st.expander(label=recipe['label']):
- # Display the recipe image
- st.markdown(f'<p style="text-align: center">><img src="{recipe["image"]}" class="image">', unsafe_allow_html=True)
- # Display the list of ingredients
- st.subheader("Ingredients:")
- for ingredient in recipe['ingredientLines']:
- st.write("-" + ingredient) #put a "-" infront for a better design
- # Display nutrition information and plot
- st.subheader("In comparison to the suggested daily intake:")
- plot_nutrition(recipe)
- # Display a link to the full recipe
- st.markdown("Find this recipe "+f'[here]({recipe["url"]})')
- # Create share message for each recipe
- share_message = f"Check out this recipe: {recipe['label']}! It's so delicious! What an amazing site!"
- # Social media sharing links, LinkedIn does not work anymore
- st.markdown(f"""<div class="share-banner">
- Share this recipe:
- <a href="https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fdailycalories.com"e={share_message}" target="_blank">Facebook</a>
- <a href="https://twitter.com/intent/tweet?text={share_message}&url=http%3A%2F%2Fdailycalories.com" target="_blank">Twitter</a>
- <a href="https://www.linkedin.com/sharing/share-offsite/?url=http%3A%2F%2Fdailycalories.com&summary={share_message}" target="_blank">LinkedIn</a>
- </div>""", unsafe_allow_html=True)
- else:
- # Error message if no recipes found
- st.error("No recipes found. Please try different criteria.")
- # Run the Streamlit app
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement