Coding History/Team Project

팀플) 혜성데이터를 활용해 유성우를 정밀하게 계산하기 위한 전략. (긴 주기의 혜성의 멀어짐과 가까워짐을 판단.)

BlackBirdIT 2024. 10. 23. 22:28
  1. 혜성 접근 데이터 저장:
    • 각 혜성의 접근 데이터를 1년 단위로 요청하고, 이를 최대 50년~100년DB에 저장할 계획.
    • 이렇게 하면 각 혜성별로 50~100개의 접근 데이터가 저장되게 된다. 지금 다루고 있는 혜성이 총 8개이기 때문에 총 400~800개의 접근 데이터가 생김.
  2. 유성우 가시성 평가에 접근 데이터 활용:
    • 저장된 혜성 접근 데이터를 바탕으로 유성우 가시성 평가에 적용.
    • 유성우 발생 시기와 혜성 접근 시기를 비교하여 혜성이 가까울수록 유성우 가시성 평가에 높은 점수를 부여함.
    • 이렇게 함으로써 가까운 혜성일수록 더 잘 보인다는 점을 반영할 수 있음.
  3. 가시성 평가 기준 설정:
    • 유성우가 발생하는 시기가 반드시 혜성이 지구에 가까이 접근하는 시기와 일치하지는 않지만, 혜성이 지구에 가까운 경우 가시성이 더 좋아질 가능성이 높기 때문에, 이를 가중치로 반영할 계획.
    • 1년치 데이터를 저장하고, 유성우 발생 시점에 해당 혜성이 얼마나 가까이 있는지 평가하여 가시성 기준을 설정할 수 있음.

결론적으로, 혜성의 접근 데이터를 저장하고 이를 바탕으로 유성우의 가시성을 데이터 기반으로 예측하고 평가하려는 계획. 혜성이 가까운 시기일수록 가시성 평가에 더 높은 점수를 부여함으로써 유성우 관측 가능성을 더 정확하게 예측하고자 하는 목적.


이랬었는데, 이래놓고 로직 분리하고 엔드포인트 만들고 테스트 중에 일단 이런 해결 방법이 생각났다.

혜성의 근접과 멀어짐을 판단하는 방법:

  1. 혜성의 델타 값(delta): 혜성과 지구 사이의 거리 값을 나타내는 delta 값이 줄어들고 있다면 혜성이 지구에 가까워지고 있는 중이고, 반대로 증가하고 있다면 멀어지고 있는 중이라는 것을 의미.
  2. 속도 값(deldot): deldot 값은 혜성과 지구 사이의 거리 변화율을 나타냄. deldot이 음수면 혜성이 지구에 가까워지고 있다는 뜻이고, 양수면 멀어지고 있다는 뜻.

예를 들어, 혜성 접근 데이터를 사용할 때:

  • delta 값이 점점 줄어들고 있고, deldot 값이 음수라면 혜성이 지구에 가까워지고 있는 중이야.
  • 반대로 delta 값이 증가하고 있고, deldot 값이 양수라면 혜성이 지구로부터 멀어지고 있는 중이라는 것을 의미.

사실 내가 혜성의 주기와 소주기? 때문에 골머리를 앓아서 방식을 바꿔보려고 DB 저장 까지 얘기가 나왔던 것이고,

일단 왜 그렇냐면,

이 결과를 보면 알 수가 있다. 지금 터틀 혜성이 멀어지고 있는 중이라서 24년도의 가장 가까운 혜성을 뽑으면 1월1일이 되어버려서 유성우의 극대기로 계산을 할 수 없는 상황. 하지만 이게 멀어지고 있는중인지 가까워지고 있는중인지 판단을 해서 계산한 후에 뽑아낸다면 결과가 다르지 않을까? 란 생각에 도달했다. 그래서 이걸 어떻게 판단하는지 알아내서 위에 쓴 글처럼 저렇게 판단하면 된다.

하지만 이 주기는 혜성마다 다르기 때문에 엔드포인트는 그대로 두고 혜성을 모두 나눠서 메서드를 호출할 수 있게 리팩토링을 해야겠다는 생각을 했다.

그래서 일단 리팩토링 하는김에

전부 다 해버렸다.

저기 보면 HalleryTuttle이 나누어져 있는 것도 확인가능하다.


고친 로직을 테스트하려고 하고 있었는데 문제가 생겼음.

        start_date_obj = datetime.strptime(start_date, '%Y-%m-%d')
        print(f"[DEBUG] Start date object for Tuttle: {start_date_obj} (Type: {type(start_date_obj)})")

        # 혜성 접근 이벤트 데이터 가져오기
        raw_data = get_comet_approach_events('Tuttle', start_date_obj, range_days)

타입으로 에러가 떠서 타입 죄다 찍어봤고..

위에 여기는 dateTime이다. 여기서는 제대로 요청해서 데이터를 가져온다.

그리고 tuttle에서도

Request record-Num URL: https://ssd.jpl.nasa.gov/api/horizons.api?format=text&COMMAND=%278P%27&OBJ_DATA=NO
2024-10-23T06:49:01.737222928Z Response Status Code: 200
2024-10-23T06:49:01.737226678Z Extracted Latest Record Number: 90000180

이렇게 잘 뽑아오고,

그런데 문제는 그 다음. 멀어진다고 판단한 뒤에 재요청시.

Extracted Latest Record Number: 90000180
2024-10-23T06:49:00.622075720Z Request Comet URL: https://ssd.jpl.nasa.gov/api/horizons.api?format=json&COMMAND=%2790000180%27&CENTER=%27500%40399%27&MAKE_EPHEM=YES&EPHEM_TYPE=OBSERVER&OBJ_DATA=YES&START_TIME=%272024-01-01%27&STOP_TIME=%272024-12-31%27&STEP_SIZE=%271+d%27&QUANTITIES=%271%2C2%2C19%2C20%2C23%2C25%27

여기 다음 url 요청이 정상적으로 이루어져야되는데

Extracted Latest Record Number: 90000180
2024-10-23T06:49:01.737915178Z [ERROR] Error in get_tuttle_approach_data: 
can only concatenate str (not "datetime.timedelta") to str

url 요청에서 어떤 문제가 생기는 것 같다.

그래서 url 요청시 넣는 날짜 값에 집중을 했다.

        # 혜성이 멀어지고 있는 경우 다음 12월의 접근 데이터로 이동
        if deldot > 0:
            next_december = datetime(approach_time.year, 12, 1)
            print(f"[DEBUG] Next December date set to (before adjustment): {next_december} (Type: {type(next_december)})")
            if approach_time.month >= 12:
                next_december = datetime(approach_time.year + 1, 12, 1)
            print(f"[DEBUG] Next December date set to (after adjustment if needed): {next_december} (Type: {type(next_december)})")

            # 다음 12월로 접근 데이터를 가져오기
            raw_data = get_comet_approach_events('Tuttle', next_december, range_days)

            if not raw_data or "error" in raw_data or not raw_data.get('data'):
                return {"error": "No comet approach data available for the adjusted date."}

이게 고친거고 중간에 사족이 들어있어서 문제였던 것.

# 다음 12월로 접근 데이터를 가져오기
next_december_str = next_december.strftime('%Y-%m-%d')  # datetime -> string 변환
print(f"[DEBUG] Next December date string for request: {next_december_str} (Type: {type(next_december_str)})")
raw_data = get_comet_approach_events('Tuttle', next_december_str, range_days)

굳이 String 변환을 할 필요가 없었다. (호라이즌 처리하는 곳에서 한다)

여튼 해결 완료.

결과값보면 12월 근사치로 뽑는다.

그리고 다른 것도 적용하면서 느낀 문제인데. 지금은 단순히 음수와 양수로만 판단하는데(지금은 딱히 문제가 되지 않는다.), 이제 겹치는 부분이 분명히 존재할 것이다. 그렇다면 이를 감지할 로직이 필요하다고 생각이 들었다.

def detect_closing_or_receding(sorted_data):
    """
    정렬된 혜성 접근 데이터를 분석하여 멀어짐의 변화를 감지하고, 가까워지는 시점을 찾는 함수.
    접근 이벤트를 분석하여 혜성이 멀어지는지, 아니면 가까워지는지 판단한다.

    Args:
        sorted_data (list): 정렬된 혜성 접근 이벤트 데이터 리스트.

    Returns:
        dict: 혜성이 가까워지는지 멀어지는지에 대한 정보.
    """
    try:
        if not sorted_data:
            return {"error": "No sorted data available for analysis."}

        # 지구와 가장 가까운 접근 이벤트 찾기
        closest_approach = min(sorted_data, key=lambda x: float(x['delta']))
        closest_index = sorted_data.index(closest_approach)

        # 현재 접근 이벤트가 멀어지고 있는지 감지
        deldot = float(closest_approach['deldot'])
        if deldot > 0:  # 현재 멀어지고 있는 경우
            # 멀어지고 있다면 이후 다시 가까워지는 시점을 찾는다.
            for event in sorted_data[closest_index + 1:]:
                if float(event['deldot']) < 0:  # 다시 가까워지는 시점 발견
                    return {
                        "status": "receding",
                        "next_closest_approach": event,
                        "message": "Comet is getting closer again."
                    }

            # 계속 멀어지고 있는 경우
            return {
                "status": "receding",
                "message": "Comet continues to recede."
            }

        # 멀어지지 않고 계속 가까워지는 경우
        return {
            "status": "closing",
            "message": "Comet is continuously approaching."
        }

    except Exception as e:
        return {"error": f"Failed to detect closing or receding status: {str(e)}"}

이게 감지 로직이고..

이걸 이제 Tuttle로직에 엮어서.. 결과를 도출시켰다.

이런 결과를 얻어냈고, 해당 결과로 이제 24년도 유성우도 판단해 낸다고 보면 된다.

유성우에 대해선 이렇게 결과가 나온다.

지금 나오는 결과는 DB 저장후에 위치 정보를 받아서 처리하는 로직을 만들거라,, Halley에 대한 요청을 처리하는 로직을 짜면서 혜성에서 나온 결과값을 추가도 해줬다.

오케이 이러면 일단 끝이다. 나머지 혜성의 요청도 받아주고 난 이후, DB에 어떻게 저장할 것인가를 우선 고민하고, 저장하고 난 이후에는 그걸 갖고 위치 정보를 받아서 저장하고 일몰 일출의 적용과 방위 같은 것을 결과로 내어주면 될듯.