Advertisement
killtdj

Untitled

Oct 30th, 2024
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.54 KB | None | 0 0
  1. import streamlit as st
  2. import geojson
  3. from shapely.geometry import shape, mapping
  4. from shapely.ops import unary_union
  5. from transformers import pipeline
  6. import geopandas as gpd
  7. from difflib import get_close_matches
  8. import re
  9.  
  10. # Initialize the LLM pipeline
  11. classifier = pipeline(
  12. "text-classification",
  13. model="facebook/bart-large-mnli",
  14. return_all_scores=True
  15. )
  16.  
  17. # Define command patterns and their variations
  18. COMMAND_PATTERNS = {
  19. "fix invalid geometries": [
  20. r"fix.*invalid",
  21. r"repair.*invalid",
  22. r"correct.*invalid",
  23. r"invalid.*fix",
  24. r"geometry.*invalid",
  25. r"fix.*geometry",
  26. r"invalid.*repair",
  27. r"broken.*geometry",
  28. r"fix.*broken",
  29. ],
  30. "fix self intersections": [
  31. r"self.*intersect",
  32. r"intersect.*self",
  33. r"crossing.*lines",
  34. r"overlapping.*lines",
  35. r"fix.*intersect",
  36. r"repair.*intersect",
  37. r"intersections.*fix",
  38. ],
  39. "remove duplicate vertices": [
  40. r"duplicate.*vertex",
  41. r"duplicate.*vertices",
  42. r"remove.*duplicate",
  43. r"delete.*duplicate",
  44. r"double.*points",
  45. r"repeated.*vertex",
  46. r"duplicate.*points",
  47. ],
  48. "fix overlaps": [
  49. r"overlap.*fix",
  50. r"fix.*overlap",
  51. r"repair.*overlap",
  52. r"overlapping.*areas",
  53. r"overlapping.*polygons",
  54. r"merge.*overlap",
  55. ],
  56. "simplify geometry": [
  57. r"simplify",
  58. r"make.*simple",
  59. r"reduce.*vertices",
  60. r"smooth.*geometry",
  61. r"generalize",
  62. r"clean.*geometry",
  63. ],
  64. "validate geometry": [
  65. r"validate",
  66. r"check.*valid",
  67. r"verify.*geometry",
  68. r"geometry.*valid",
  69. r"check.*geometry",
  70. ]
  71. }
  72.  
  73. def preprocess_text(text):
  74. # Common typo corrections
  75. typo_corrections = {
  76. 'geomtry': 'geometry',
  77. 'geometrie': 'geometry',
  78. 'intersecton': 'intersection',
  79. 'intersections': 'intersection',
  80. 'vertice': 'vertex',
  81. 'verticies': 'vertices',
  82. 'duplicat': 'duplicate',
  83. 'simplifie': 'simplify',
  84. 'overlaping': 'overlapping',
  85. 'repare': 'repair',
  86. 'invalide': 'invalid'
  87. }
  88.  
  89. words = text.lower().split()
  90. corrected_words = []
  91.  
  92. for word in words:
  93. if word in typo_corrections:
  94. corrected_words.append(typo_corrections[word])
  95. else:
  96. # Find close matches in our vocabulary
  97. vocab = list(typo_corrections.keys()) + list(typo_corrections.values())
  98. matches = get_close_matches(word, vocab, n=1, cutoff=0.8)
  99. if matches:
  100. corrected_words.append(matches[0])
  101. else:
  102. corrected_words.append(word)
  103.  
  104. return ' '.join(corrected_words)
  105.  
  106. def identify_command(text):
  107. text = preprocess_text(text)
  108.  
  109. for command, patterns in COMMAND_PATTERNS.items():
  110. for pattern in patterns:
  111. if re.search(pattern, text, re.IGNORECASE):
  112. return command
  113.  
  114. # If no direct match, use the LLM classifier
  115. results = classifier(text, list(COMMAND_PATTERNS.keys()))
  116. return max(results[0], key=lambda x: x['score'])['label']
  117.  
  118. def fix_geometry(geojson_data, command, tolerance=0.01):
  119. fixed_features = []
  120. stats = {
  121. 'fixed_count': 0,
  122. 'total_count': len(geojson_data['features']),
  123. 'command': command
  124. }
  125.  
  126. for feature in geojson_data['features']:
  127. original_geom = shape(feature['geometry'])
  128. fixed_geom = original_geom
  129.  
  130. try:
  131. if command == "fix invalid geometries" or command == "fix self intersections":
  132. fixed_geom = original_geom.buffer(0)
  133. if not original_geom.equals(fixed_geom):
  134. stats['fixed_count'] += 1
  135.  
  136. elif command == "remove duplicate vertices":
  137. fixed_geom = original_geom.simplify(0, preserve_topology=True)
  138. if not original_geom.equals(fixed_geom):
  139. stats['fixed_count'] += 1
  140.  
  141. elif command == "fix overlaps":
  142. fixed_geom = unary_union([original_geom])
  143. if not original_geom.equals(fixed_geom):
  144. stats['fixed_count'] += 1
  145.  
  146. elif command == "simplify geometry":
  147. fixed_geom = original_geom.simplify(tolerance)
  148. if not original_geom.equals(fixed_geom):
  149. stats['fixed_count'] += 1
  150.  
  151. elif command == "validate geometry":
  152. if not original_geom.is_valid:
  153. fixed_geom = original_geom.buffer(0)
  154. stats['fixed_count'] += 1
  155.  
  156. feature['geometry'] = mapping(fixed_geom)
  157. fixed_features.append(feature)
  158.  
  159. except Exception as e:
  160. st.warning(f"Error processing feature: {str(e)}")
  161. fixed_features.append(feature)
  162.  
  163. return {'type': 'FeatureCollection', 'features': fixed_features}, stats
  164.  
  165. def generate_response(stats):
  166. if stats['fixed_count'] == 0:
  167. return f"No geometries needed fixing for {stats['command']}"
  168. else:
  169. return f"Fixed {stats['fixed_count']} out of {stats['total_count']} geometries using {stats['command']}"
  170.  
  171. def main():
  172. st.title("Smart GeoJSON Geometry Fixer")
  173. st.write("Upload a GeoJSON file and use natural language commands to fix geometry issues.")
  174.  
  175. # Add custom CSS for better chat display
  176. st.markdown("""
  177. <style>
  178. .chat-message {
  179. padding: 1rem;
  180. border-radius: 0.5rem;
  181. margin-bottom: 1rem;
  182. }
  183. .user-message {
  184. background-color: #e6f3ff;
  185. }
  186. .assistant-message {
  187. background-color: #f0f2f6;
  188. }
  189. </style>
  190. """, unsafe_allow_html=True)
  191.  
  192. uploaded_file = st.file_uploader("Upload GeoJSON", type="geojson")
  193.  
  194. if 'geojson_data' not in st.session_state and uploaded_file is not None:
  195. st.session_state.geojson_data = geojson.load(uploaded_file)
  196.  
  197. if 'chat_history' not in st.session_state:
  198. st.session_state.chat_history = []
  199.  
  200. if 'current_geojson' not in st.session_state and uploaded_file is not None:
  201. st.session_state.current_geojson = st.session_state.geojson_data
  202.  
  203. # Command suggestions
  204. st.header("Example Commands")
  205. example_commands = [
  206. "Fix invalid geometries in this file",
  207. "Can you remove duplicate vertices?",
  208. "Please fix self intersections",
  209. "Check for overlapping areas",
  210. "Simplify the geometry",
  211. "Validate all geometries"
  212. ]
  213. for cmd in example_commands:
  214. st.write(f"- {cmd}")
  215.  
  216. user_input = st.text_input("Enter your command:")
  217.  
  218. if user_input:
  219. st.session_state.chat_history.append(("User", user_input))
  220.  
  221. command = identify_command(user_input)
  222.  
  223. if hasattr(st.session_state, 'current_geojson'):
  224. fixed_geojson, stats = fix_geometry(st.session_state.current_geojson, command)
  225. st.session_state.current_geojson = fixed_geojson
  226.  
  227. response = generate_response(stats)
  228. st.session_state.chat_history.append(("Assistant", response))
  229.  
  230. # Display the fixed GeoJSON
  231. st.subheader("Current GeoJSON State")
  232. st.json(fixed_geojson)
  233.  
  234. # Download options
  235. col1, col2 = st.columns(2)
  236. with col1:
  237. st.download_button(
  238. label="Download GeoJSON",
  239. data=geojson.dumps(fixed_geojson),
  240. file_name="fixed_geometry.geojson",
  241. mime="application/geo+json"
  242. )
  243. with col2:
  244. if stats['fixed_count'] > 0:
  245. st.success(f"✅ Fixed {stats['fixed_count']} issues")
  246. else:
  247. st.info("✓ No issues found")
  248.  
  249. # Display chat history with styling
  250. st.subheader("Chat History")
  251. for role, message in st.session_state.chat_history:
  252. css_class = "user-message" if role == "User" else "assistant-message"
  253. st.markdown(f'<div class="chat-message {css_class}"><b>{role}:</b> {message}</div>', unsafe_allow_html=True)
  254.  
  255. if __name__ == "__main__":
  256. main()
  257.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement