Skip to content

Commit

Permalink
Working in two types of batch, you can provide a list
Browse files Browse the repository at this point in the history
of images, so the API will search for its features
or you can search for it based on the features
  • Loading branch information
frasanz committed Oct 25, 2024
1 parent deb19c4 commit b7d7243
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 36 deletions.
89 changes: 53 additions & 36 deletions georeferencing/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from .forms import PrettyJSONWidget
from .models import Batch, Image, GeoAttempt
from .tasks import download_image
from .tasks import download_image, generate_from_list


class BatchAdminForm(forms.ModelForm):
Expand Down Expand Up @@ -96,7 +96,7 @@ def fetch_api_data(self, request):
original_images = request.GET.get('originalImages', '')
url = 'https://eol.jsc.nasa.gov/SearchPhotos/PhotosDatabaseAPI/PhotosDatabaseAPI.pl'

if original_images:
if 0:
result = '['
# original images can be a list of images separated by new line
for image in original_images.split(','):
Expand All @@ -115,7 +115,7 @@ def fetch_api_data(self, request):
result += response.text[1:-1]+','
except requests.RequestException as e:
return JsonResponse({'success': False, 'error': str(e)})
return JsonResponse({'success': True, 'result': result})
return JsonResponse({'success': True, 'result': result[0:-1]+']'})
else:
query = 'query=images|directory|like|*large*' # Default query
if feat_value:
Expand All @@ -135,7 +135,7 @@ def fetch_api_data(self, request):
try:
response = requests.get(url_request, timeout=5)
if response.status_code == 200:
return JsonResponse({'success': True, 'result': response.text+']'})
return JsonResponse({'success': True, 'result': response.text})
else:
return JsonResponse({'success': False, 'error': f'Error {response.status_code}'})
except requests.RequestException as e:
Expand All @@ -151,47 +151,64 @@ def changeform_view(self, request, object_id=None, form_url='', extra_context=No
def save_model(self, request, obj, form, change):
if not change:
obj.user = request.user
obj.save()

# Now, we create the images based on result, for each item in result
# we create an image and assign it to the batch
if obj.result:
for item in obj.result:
datetime_str = item['frames.pdate'] + \
' ' + item['frames.ptime']
formated_datetime = datetime.strptime(
datetime_str, '%Y%m%d %H%M%S')
large_image_url = (
f"https://eol.jsc.nasa.gov/DatabaseImages/"
f"{item['images.directory']}/{item['images.filename']}"
)
image = Image.objects.create(
name=item['images.filename'],
taken=formated_datetime,
focalLength=item['frames.fclt'],
photoCenterPoint=f"{item['frames.lat']}, {item['frames.lon']}",
spacecraftNadirPoint=f"{item['frames.nlat']}, {item['frames.nlon']}",
link=
f"https://eol.jsc.nasa.gov/SearchPhotos/photo.pl?mission="
f"{item['frames.mission']}"
f"&roll={item['frames.roll']}&frame={item['frames.frame']}",
largeImageURL=large_image_url,
batch=obj,
replicas=obj.replicas
)
image.save()

# Now, add to django-rq queue the download of the large image
# The fields to save will depend on batch type
if obj.type == 'SEARCH':
obj.originalImages = ''
obj.save()


# Now, we create the images based on result, for each item in result
# we create an image and assign it to the batch
if obj.result:
for item in obj.result:
datetime_str = item['frames.pdate'] + \
' ' + item['frames.ptime']
formated_datetime = datetime.strptime(
datetime_str, '%Y%m%d %H%M%S')
large_image_url = (
f"https://eol.jsc.nasa.gov/DatabaseImages/"
f"{item['images.directory']}/{item['images.filename']}"
)
image = Image.objects.create(
name=item['images.filename'],
taken=formated_datetime,
focalLength=item['frames.fclt'],
photoCenterPoint=f"{item['frames.lat']}, {item['frames.lon']}",
spacecraftNadirPoint=f"{item['frames.nlat']}, {item['frames.nlon']}",
link=
f"https://eol.jsc.nasa.gov/SearchPhotos/photo.pl?mission="
f"{item['frames.mission']}"
f"&roll={item['frames.roll']}&frame={item['frames.frame']}",
largeImageURL=large_image_url,
batch=obj,
replicas=obj.replicas
)
image.save()

# Now, add to django-rq queue the download of the large image

download_image.delay(image)
elif obj.type == 'LIST':
obj.originalImages = form.cleaned_data['originalImages']
obj.feat = None
obj.mission = None
obj.result = None
obj.fcltle = None
obj.fcltge = None
obj.save()
generate_from_list.delay(obj.originalImages)

# Now, we create the images and the geoattempt for each image

download_image.delay(image)


class ImageAdmin(admin.ModelAdmin):
"""
ImageAdmin is a Django ModelAdmin class for managing Image model instances
in the admin interface.
"""
list_display = ('name', 'createdDateTime', 'geoattempts_count')
list_display = ('name', 'batch', 'createdDateTime', 'geoattempts_count')
list_filter = ('createdDateTime', 'batch')
search_fields = ('name',)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.16 on 2024-10-25 21:03

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('georeferencing', '0034_batch_originalimages'),
]

operations = [
migrations.AddField(
model_name='batch',
name='type',
field=models.CharField(choices=[('SEARCH', 'Search'), ('LIST', 'List')], default='SEARCH', max_length=20),
),
migrations.AlterField(
model_name='batch',
name='originalImages',
field=models.TextField(blank=True, null=True, verbose_name='Original images'),
),
]
11 changes: 11 additions & 0 deletions georeferencing/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class GeoAttempt(models.Model):
('ASSIGNED', 'Assigned'),
('DONE', 'Done'),
)



image = models.ForeignKey('Image', on_delete=models.CASCADE)
assignedUser = models.ForeignKey(get_user_model(), on_delete=models.DO_NOTHING, blank=True, null=True)
Expand Down Expand Up @@ -65,8 +67,17 @@ def __str__(self):


class Batch(models.Model):
BATCH_CHOICES = (
('SEARCH', 'Search'),
('LIST', 'List'),
)

name = models.CharField(max_length=100)
createdDateTime = models.DateTimeField(auto_now_add=True)
type = models.CharField(
max_length=20,
choices = BATCH_CHOICES,
default = 'SEARCH')
# Search fields
feat = models.CharField(max_length=100, blank = True, null = True)
mission = models.CharField(max_length=100, blank = True, null = True)
Expand Down
40 changes: 40 additions & 0 deletions georeferencing/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,43 @@ def download_image(image):
print(f"GeoAttempt created for image {image}: {geoattemp.id}")
geoattemp.save()

@job('default') # Specify the queue (default, high, low) here
def generate_from_list(image_list):
"""
generate_from_list is a function that takes a list of Image objects and generates GeoAttempts for each image.
"""
for image in image_list:
# We do the query to the API for each image
url = 'https://eol.jsc.nasa.gov/SearchPhotos/PhotosDatabaseAPI/PhotosDatabaseAPI.pl'
query = 'query=images|directory|like|*large*'
query = f'{query}&query=images|name|like|*{image}*'
url_request = (
f'{url}?{query}&return=images|directory|images|filename|'
f'nadir|lat|nadir|lon|nadir|elev|nadir|azi|camera|fclt'
f'&key={key}'
)
try:
response = requests.get(url_request, timeout=5)
if response.status_code == 200:
data = response.json()
# We create the image object
image = Image.objects.create(
name = data['images'][0]['filename'],
taken = timezone.now(),
camera = data['images'][0]['camera'],
focalLength = data['images'][0]['fclt'],
spacecraftNadirPoint = f"{data['images'][0]['nadir']['lat']}, {data['images'][0]['nadir']['lon']}",
spaceCraftAltitude = data['images'][0]['nadir']['elev'],
largeImageURL = data['images'][0]['directory'] + data['images'][0]['filename'],
replicas = 5
)
print(f"Image created: {image.name}")
# We download the image
download_image.delay(image)
else:
print(f"Failed to query image: {image}")
except requests.exceptions.RequestException as e:
print(f"Failed to query image: {image}: {e}")
return None


Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,60 @@
autoCloseBrackets: true,
readOnly: true
});

const typeField = $('#id_type');

/* Not using it, but keeping */
function clearAllFields(){
$('input[name="feat"]').val('');
$('input[name="mission"]').val('');
$('input[name="fcltle"]').val('');
$('input[name="fcltge"]').val('');
$('textarea[name="result"]').val('');
$('input[name="numberImages"]').val('');
$('textarea[name="originalImages"]').val('');
}

function countImages(){
console.log('counting images');
const images = $('textarea[name="originalImages"]').val();
const imagesArray = images.split(',');
$('input[name="numberImages"]').val(imagesArray.length-1);
}

function toogleType(){
if(typeField.val() === 'SEARCH'){
console.log('search');
// Hide the originalImages field
$('textarea[name="originalImages"]').closest('.form-row').hide();

// Show others fields
$('input[name="feat"]').closest('.form-row').show();
$('input[name="mission"]').closest('.form-row').show();
$('input[name="fcltle"]').closest('.form-row').show();
$('input[name="fcltge"]').closest('.form-row').show();
$('textarea[name="result"]').closest('.form-row').show();
$('#fetch-data-btn').show();

} else {
console.log('list');
// Show the originalImages field
$('textarea[name="originalImages"]').closest('.form-row').show();
// Hide others fields
$('input[name="feat"]').closest('.form-row').hide();
$('input[name="mission"]').closest('.form-row').hide();
$('input[name="fcltle"]').closest('.form-row').hide();
$('input[name="fcltge"]').closest('.form-row').hide();
$('textarea[name="result"]').closest('.form-row').hide();
$('#fetch-data-btn').hide();
}
}

// Count images if textarea we are typing
$('textarea[name="originalImages"]').on('input', countImages);

toogleType();
typeField.on('change', toogleType);
});
</script>
{% endblock %}

0 comments on commit b7d7243

Please sign in to comment.