Skip to content

Commit 6555181

Browse files
authored
Merge branch 'python-geeks:main' into main
2 parents 87a133d + c3902cf commit 6555181

File tree

18 files changed

+772
-8
lines changed

18 files changed

+772
-8
lines changed

iss_tracker/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# ISS Tracker 🛰️
2+
A Python script to fetch TLE data of the ISS (ZARYA) satellite, calculate its position, predict its orbit and visualize its trajectory on an interactive map. Thanks to [Celestrak](https://celestrak.org/) We can access to the TLE data of satellites, including International Space Station.
3+
4+
## How to Run
5+
- Install required modules: `pip install -r requirements.txt`
6+
- Run the script: `python3 tracker.py`
7+
- Wait for the map to launch.
8+
9+
## Key Concepts
10+
### What is a TLE?
11+
A Two-Line Element Set (TLE) is a standardized format used to describe the orbit of a satellite. It consists of two lines of data that include important orbital parameters, such as the satellite's position, velocity, and other relevant information at a specific time known as the epoch (Source: ["Two-line-element set"](https://en.wikipedia.org/wiki/Two-line_element_set)).
12+
13+
### What is a Geocentric Position?
14+
A geocentric position refers to a viewpoint or coordinate system that is centered on the Earth. In astronomy, it describes a model where the Earth is considered the center of the universe, with celestial bodies like the Sun and planets (or even satellites) orbiting around it (Source: ["Earth-centered, Earth-fixed coordinate system"](https://en.wikipedia.org/wiki/Earth-centered,_Earth-fixed_coordinate_system) and ["Geocentric model"](https://en.wikipedia.org/wiki/Geocentric_model)).
15+
16+
### What is a Subpoint Position?
17+
In Astronomy, the subpoint position (or subsatellite point) of a satellite refers to the point on the Earth's surface that is directly beneath the satellite at any given moment. It is defined by its geographical coordinates, latitude and longitude (Source: ["Geodesy for the Layman" by U.S. Geological Survey](https://www.ngs.noaa.gov/PUBS_LIB/Geodesy4Layman/TR80003D.HTM#ZZ9)). This point is significant because it represents the satellite's ground track, which is the path that the satellite appears to trace over the Earth's surface as it orbits (Source: ["Satellite Communications" by Dennis Roddy](https://books.google.com/books/about/Satellite_Communications_Fourth_Edition.html?id=2KEt_hFyjwgC)).
18+
19+
### What is International Date Line (IDL)?
20+
The International Date Line is an imaginary line that runs from the North Pole to the South Pole, primarily along the 180th meridian in the Pacific Ocean. It serves as the boundary between two consecutive calendar dates, meaning when you cross it, you either gain or lose a day depending on the direction you are traveling (Source: ["The international date line, explained"](https://www.livescience.com/44292-international-date-line-explained.html) and ["International Date Line"](https://www.britannica.com/topic/International-Date-Line)).
21+
22+
### What libraries are used in the script?
23+
- `Skyfield` ([Documentation](https://rhodesmill.org/skyfield/))
24+
- `Folium` ([Documentation](https://python-visualization.github.io/folium/latest/index.html))
25+
- `Selenium` ([Documentation](https://www.selenium.dev/documentation/))
26+
- `Datetime` ([Documentation](https://docs.python.org/3/library/datetime.html))
27+
- `Time` ([Documentation](https://docs.python.org/3/library/time.html))
28+
- `OS` ([Documentation](https://docs.python.org/3/library/os.html))
29+
30+
## Output
31+
![Screenshot_1](https://github.com/user-attachments/assets/1027863f-fe7a-46ee-abb6-daef4b6a12a3)
32+
![Screenshot_2](https://github.com/user-attachments/assets/4ee308a3-41b1-4bb0-b02a-e394f090444b)
33+
34+
## Author
35+
Mohammad Bazargan ([BazarganDev](https://github.com/BazarganDev))
36+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ISS (ZARYA)
2+
1 25544U 98067A 24284.58548122 .00037521 00000+0 67055-3 0 9998
3+
2 25544 51.6398 103.8131 0008430 61.8768 54.0890 15.49615403476441

iss_tracker/map/tracker_map.html

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
5+
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
6+
7+
<script>
8+
L_NO_TOUCH = false;
9+
L_DISABLE_3D = false;
10+
</script>
11+
12+
<style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
13+
<style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
14+
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js"></script>
15+
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
16+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
17+
<script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
18+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css"/>
19+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css"/>
20+
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css"/>
21+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css"/>
22+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
23+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>
24+
25+
<meta name="viewport" content="width=device-width,
26+
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
27+
<style>
28+
#map_b93ce63ad7602b7cbbbff28b6a0eb107 {
29+
position: relative;
30+
width: 100.0%;
31+
height: 100.0%;
32+
left: 0.0%;
33+
top: 0.0%;
34+
}
35+
.leaflet-container { font-size: 1rem; }
36+
</style>
37+
38+
</head>
39+
<body>
40+
41+
42+
<div class="folium-map" id="map_b93ce63ad7602b7cbbbff28b6a0eb107" ></div>
43+
44+
</body>
45+
<script>
46+
47+
48+
var map_b93ce63ad7602b7cbbbff28b6a0eb107 = L.map(
49+
"map_b93ce63ad7602b7cbbbff28b6a0eb107",
50+
{
51+
center: [-24.49466279314546, 174.8304784523187],
52+
crs: L.CRS.EPSG3857,
53+
zoom: 2,
54+
zoomControl: true,
55+
preferCanvas: false,
56+
}
57+
);
58+
59+
60+
61+
62+
63+
var tile_layer_b0f2ec3d4acb367411dae569d44686fd = L.tileLayer(
64+
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
65+
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
66+
);
67+
68+
69+
tile_layer_b0f2ec3d4acb367411dae569d44686fd.addTo(map_b93ce63ad7602b7cbbbff28b6a0eb107);
70+
71+
72+
var marker_b8fc8ee22221dd8c06d6f1968af1f3ad = L.marker(
73+
[-24.49466279314546, 174.8304784523187],
74+
{}
75+
).addTo(map_b93ce63ad7602b7cbbbff28b6a0eb107);
76+
77+
78+
var icon_1b762bdfb77549cf0eab72ad55ae177e = L.AwesomeMarkers.icon(
79+
{"extraClasses": "fa-rotate-0", "icon": "satellite", "iconColor": "white", "markerColor": "red", "prefix": "fa"}
80+
);
81+
marker_b8fc8ee22221dd8c06d6f1968af1f3ad.setIcon(icon_1b762bdfb77549cf0eab72ad55ae177e);
82+
83+
84+
var popup_415b721edb3f756ae8509f6ab6dd3a7c = L.popup({"maxWidth": "100%"});
85+
86+
87+
88+
var html_22cf792e75002a312b5bbcf16702a93a = $(`<div id="html_22cf792e75002a312b5bbcf16702a93a" style="width: 100.0%; height: 100.0%;">International Space Station (ZARYA)</div>`)[0];
89+
popup_415b721edb3f756ae8509f6ab6dd3a7c.setContent(html_22cf792e75002a312b5bbcf16702a93a);
90+
91+
92+
93+
marker_b8fc8ee22221dd8c06d6f1968af1f3ad.bindPopup(popup_415b721edb3f756ae8509f6ab6dd3a7c)
94+
;
95+
96+
97+
98+
99+
marker_b8fc8ee22221dd8c06d6f1968af1f3ad.bindTooltip(
100+
`<div>
101+
ISS (Lat: -24.49466279314546, Lon: 174.8304784523187)
102+
</div>`,
103+
{"sticky": true}
104+
);
105+
106+
107+
var poly_line_fd95aaab57813a5edd7da1823d63b112 = L.polyline(
108+
[[-24.49466279314546, 174.8304784523187], [-21.621759670448842, 177.41262905393498], [-18.700685873400722, 179.88510044569458], [-15.739687648306464, 182.26604285518965], [-12.74622977541998, 184.5723514473874], [-9.727157757642022, 186.81985369058035], [-6.688842065892132, 189.02351267892686], [-3.637307700241382, 191.19763664680653], [-0.5783525903980175, 193.3560897575556], [2.482341575191149, 195.51250232631867], [5.5391025126393965, 197.68048045805725], [8.586160936279613, 199.8738159745877], [11.617541011569852, 202.1066976343822], [14.626944056449638, 204.39392403561783], [17.607621832657372, 206.75111711086103], [20.552235768956205, 209.19493248700147], [23.45269861133681, 211.74325872683926], [26.299995478945643, 214.41539090537194], [29.083982406817643, 217.23215419753993], [31.793162624157702, 220.21593910160166], [34.41444470754525, 223.39059061650497], [36.932893261647926, 226.7810688551601], [39.331493006223745, 230.4127698935521], [41.590962112491255, 234.31036902883815], [43.689670630619595, 238.49603747948203], [45.603743135142956, 242.98691234214414], [47.30744544942126, 247.7918040752284], [48.773961408776586, 252.90734309829452], [49.97663859064275, 258.314106711376], [50.890702587848104, 263.9736616893207], [51.495302729208376, 269.82772007738515], [51.77558751276012, 275.8004652714232], [51.72438697288365, 281.80437954132236], [51.34308771413599, 287.7487397388982], [50.641462510733525, 293.54888748351556], [49.636501787586134, 299.1340493840284], [48.35055739189671, 304.4520940315297], [46.809233700082515, 309.4707792229043], [45.03942093494068, 314.17611172517786], [43.0677210780296, 318.5689797561918], [40.919355013664045, 322.6612034398833], [38.61751975013718, 326.4718175653756], [36.18310332158709, 330.02400984527765], [33.634650655065904, 333.34283416226015], [30.988486160673993, 336.4536396280102], [28.2589213382775, 339.381079929084], [25.458498349203822, 342.14855459045106], [22.5982389800872, 344.7779518549352], [19.68788181565584, 347.28959116638987], [16.73609937199809, 349.70229109634204], [13.750692516235175, 352.0335117052305], [10.738762758381748, 354.2995379020087], [7.706864770331067, 356.5156829566689], [4.6611423516539565, 358.6964999768141], [1.6074514134252051, 360.8559949116242], [-1.4485263616780886, 363.0078383337469], [-4.50117555073232, 365.16557548652867], [-7.544841132749383, 367.342835280184], [-10.573721193684085, 369.55353931008096], [-13.581754645582292, 371.81211163561574], [-16.562500389189434, 374.13368893935996], [-19.509004347281397, 376.53432857601285], [-22.413650894999385, 379.0312085447993], [-25.26799555414489, 381.64280801045044], [-28.06257663083526, 384.38904887954556], [-30.786705121061832, 387.29136715444633], [-33.428235226837884, 390.37266635387294], [-35.973322976278226, 393.65708361778826], [-38.40618869265097, 397.169472923572], [-40.70891143869174, 400.9344828695082], [-42.86130071689664, 404.97508821162705], [-44.840911932257725, 409.31044334893113], [-46.62329373029699, 413.95299190080704], [-48.18256853966267, 418.90492573605627], [-49.49243738393764, 424.15436334049406], [-50.52764743708105, 429.6719838266909], [-51.26585339591142, 435.4091831638401], [-51.6896531796579, 441.29888183422986], [-51.78843542070986, 447.2596737660014], [-51.55962099221179, 453.203043427122], [-51.00897688921455, 459.04224876091934], [-50.1499164448394, 464.7007800706127], [-49.00197553993526, 470.1184844182884], [-47.58884328179974, 475.25437735165156], [-45.93635889732174, 480.0862938692678], [-44.070787267839144, 484.6083090408083], [-42.01753104669398, 488.8270819321435], [-39.80029990584469, 492.75807748553245], [-37.44067185055923, 496.42225402090617], [-34.95794762802237, 499.8434641140519], [-32.36920029850538, 503.0465866461428]],
109+
{"bubblingMouseEvents": true, "color": "black", "dashArray": "5", "dashOffset": null, "fill": false, "fillColor": "black", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 1}
110+
).addTo(map_b93ce63ad7602b7cbbbff28b6a0eb107);
111+
112+
</script>
113+
</html>

iss_tracker/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
folium==0.17.0
2+
selenium==4.25.0
3+
skyfield==1.49
4+

iss_tracker/tracker.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Import necessary modules
2+
from datetime import datetime, timedelta
3+
from skyfield.iokit import parse_tle_file
4+
from skyfield.api import load
5+
from selenium import webdriver
6+
import folium
7+
import time
8+
import os
9+
10+
11+
# Constants
12+
TLE_FILENAME = "data_files/iss_zarya_tle.tle"
13+
TLE_URL = "https://celestrak.org/NORAD/elements/gp.php?CATNR=25544&FORMAT=TLE"
14+
MAP_FILENAME = "map/tracker_map.html"
15+
MAP_ZOOM_START = 2
16+
ORBIT_DURATION_MINUTES = 90
17+
UPDATE_INTERVAL_SECONDS = 60
18+
19+
20+
# Functions
21+
def download_tle_file():
22+
"""
23+
If the TLE file is missing or is outdated, download the latest data.
24+
"""
25+
if not load.exists(TLE_FILENAME) or load.days_old(TLE_FILENAME) > 1.0:
26+
try:
27+
load.download(TLE_URL, filename=TLE_FILENAME)
28+
except Exception as e:
29+
print(f"ERROR: Failed to download the TLE data.{e}")
30+
exit(1)
31+
32+
33+
def load_satellite_data():
34+
"""
35+
Load the satellite data from the TLE file.
36+
"""
37+
with load.open(TLE_FILENAME) as f:
38+
satellites = list(parse_tle_file(f, load.timescale()))
39+
# Index ISS (ZARYA) by NORADID number.
40+
return {sat.model.satnum: sat for sat in satellites}[25544]
41+
42+
43+
def create_map(sat_lat, sat_lon):
44+
"""
45+
Create a new map with the ISS's current position.
46+
"""
47+
# Create a map centered onto the ISS position.
48+
iss_map = folium.Map(
49+
location=[sat_lat, sat_lon],
50+
zoom_start=MAP_ZOOM_START
51+
)
52+
# Pinpoint the satellite's current position on the map.
53+
folium.Marker(
54+
location=[sat_lat, sat_lon],
55+
tooltip=f"ISS (Lat: {sat_lat}, Lon: {sat_lon})",
56+
popup="International Space Station (ZARYA)",
57+
icon=folium.Icon(color="red", icon="satellite", prefix="fa")
58+
).add_to(iss_map)
59+
return iss_map
60+
61+
62+
def predict_orbit(satellite, current_time):
63+
"""
64+
Predict the orbit of the satellite by predicting its future poitions.
65+
ISS completes one orbit around the Earth in approximately 90 minutes.
66+
"""
67+
# Add current position of the satellite
68+
current_sat_lat = satellite.at(current_time).subpoint().latitude.degrees
69+
current_sat_lon = satellite.at(current_time).subpoint().longitude.degrees
70+
orbit_coordinates = [(current_sat_lat, current_sat_lon)]
71+
for i in range(1, ORBIT_DURATION_MINUTES + 1):
72+
future_time = current_time + timedelta(minutes=i)
73+
future_geocentric_pos = satellite.at(future_time)
74+
future_sub_pos = future_geocentric_pos.subpoint()
75+
future_sat_lat = future_sub_pos.latitude.degrees
76+
future_sat_lon = future_sub_pos.longitude.degrees
77+
# Longitude Adjustment: Check for large jumps in longitude.
78+
if abs(future_sat_lon - orbit_coordinates[-1][1]) > 180:
79+
if future_sat_lon < orbit_coordinates[-1][1]:
80+
future_sat_lon += 360
81+
else:
82+
future_sat_lon -= 360
83+
# Add the fixed coordinates to the list of orbit coordinates.
84+
orbit_coordinates.append((future_sat_lat, future_sat_lon))
85+
return orbit_coordinates
86+
87+
88+
def main():
89+
download_tle_file()
90+
satellite = load_satellite_data()
91+
driver = webdriver.Firefox()
92+
driver.get(f"file:///{os.path.abspath(MAP_FILENAME)}")
93+
while True:
94+
current_time = datetime.utcnow()
95+
t = load.timescale().utc(
96+
current_time.year,
97+
current_time.month,
98+
current_time.day,
99+
current_time.hour,
100+
current_time.minute,
101+
current_time.second
102+
)
103+
geocentric_pos = satellite.at(t)
104+
sub_pos = geocentric_pos.subpoint()
105+
sat_lat = sub_pos.latitude.degrees
106+
sat_lon = sub_pos.longitude.degrees
107+
iss_map = create_map(sat_lat, sat_lon)
108+
orbit_coordinates = predict_orbit(satellite, t)
109+
folium.PolyLine(
110+
locations=orbit_coordinates,
111+
color="black",
112+
weight=1,
113+
dash_array="5"
114+
).add_to(iss_map)
115+
iss_map.save(MAP_FILENAME)
116+
driver.refresh()
117+
time.sleep(UPDATE_INTERVAL_SECONDS)
118+
119+
120+
# Ensure the "main" function is only executed when the script is run directly.
121+
if __name__ == "__main__":
122+
main()

language_detection/langdetect.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from langdetect import detect
2+
3+
text = input("Enter Any text in any language: ")
4+
print(detect(text))

language_detection/readme.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Language Detection Tool
2+
# Language Detection Tool
3+
4+
This is a simple Python tool that detects the language of the input text using the `langdetect` library. You can enter any text in any language, and the program will automatically detect and display the language code.
5+
6+
## Features
7+
8+
- Detects the language of any given text input.
9+
- Supports multiple languages.
10+
- Simple and easy to use.
11+
12+
## Prerequisites
13+
14+
Before running the project, you need to have Python installed on your machine. Additionally, you need to install the `langdetect` library.
15+
16+
## Installation
17+
18+
## Installation
19+
20+
To install the required library, you can use the following command:
21+
22+
```bash
23+
pip install langdetect
24+
```
25+
26+
Alternatively, you can install it from the `requirements.txt` file:
27+
28+
```bash
29+
pip install -r requirements.txt
30+
```
31+
32+
## Usage
33+
34+
```python
35+
from langdetect import detect
36+
37+
text = "Your text here"
38+
language = detect(text)
39+
print(f"The detected language is: {language}")
40+
```
41+
42+
## License
43+
44+
This project is licensed under the MIT License.

language_detection/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
langdetect==1.0.9

uv_sunscreen_advisor/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# UV Index and Sunscreen Advisor
2+
3+
This Python script fetches the current UV index for a given location and provides personalized sunscreen advice based on the UV index and whether the user is indoors or outdoors.
4+
5+
## Features
6+
7+
- Fetches real-time UV index data based on user-provided latitude and longitude.
8+
- Provides personalized sunscreen advice based on UV exposure:
9+
- Low UV index: minimal protection recommended.
10+
- Moderate to extreme UV index: higher SPF and protective measures are suggested.
11+
- Differentiates advice for indoor and outdoor scenarios.
12+
13+
## Requirements
14+
15+
- Python 3.x
16+
- `requests` library for making HTTP API requests.
17+
18+
## Setup
19+
20+
### Install the required libraries:
21+
22+
```bash
23+
pip install requests

0 commit comments

Comments
 (0)