4 <& /util/import_javascript.mas, classes => [ 'jquery.iframe-post-form', 'CXGN.BreederSearch', 'CXGN.Trial', 'moment_min', 'daterangepicker' ] &>
6 <div class="modal fade" id="upload_drone_imagery_dialog" name="upload_drone_imagery_dialog" tabindex="-1" role="dialog" aria-labelledby="uploadDroneImageryDialog">
7 <div class="modal-dialog modal-xl" role="document">
8 <div class="modal-content">
9 <div class="modal-header">
10 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
11 <h4 class="modal-title" id="uploadDroneImageryDialog">Upload Drone Imagery</h4>
13 <div class="modal-body">
14 <div class="container-fluid">
16 <form class="form-horizontal" role="form" method="post" enctype="multipart/form-data" encoding="multipart/form-data" id="upload_drone_imagery_form" name="upload_drone_imagery_form">
18 <&| /util/workflow.mas, id=> "drone_imagery_upload_workflow" &>
19 <&| /util/workflow.mas:step, title=> "Intro" &>
20 <& /page/page_title.mas, title=>"This workflow will guide you through uploading aerial images to the database" &>
21 <p>Your field trial must already be in the database before you can upload images for it. Please go to <a href="/breeders/trials">Manage->Field Trials</a> if it is not.</p>
22 <p>A field trial represents plots in the field where each plot has a globally unique <i>plot_name</i>, a sequential <i>plot_number</i> that is unique in the trial (e.g. 101, 102, 103 for three separate plots), and an <i>accession_name</i> representing the genotype being tested in that plot. Each plot can belong to different blocks (<i>block_number</i>) and reps (<i>rep_number</i>) depending on the experimental design you are using (e.g. complete block vs augmented design). Each plot can have a <i>row_number</i> and <i>col_number</i> indicating the relative position of the plot in the field. A field trial can represent a yield trial, a phenotyping trial, a crossing block, a greenhouse, a nursery, etc.</p>
23 <p>If you have raw aerial images that have not been stitched into an orthophotomosaic image of the whole field, your raw images should be uploaded using a zipfile (.zip). You can have several drone runs for a single field trial. For an individual drone run, once you have uploaded all photos, you can stitch an orthophotoimage together. Afterwards, you will have options to cut the ortho image into plot polygons and extract phenotypes for those plots into the database. The maximum zipfile size is 2GB.</p>
24 <p>If you already have an orthophotomosaic image of your entire field, you can upload that image under a field trial and a drone run. Afterwards, you will have options to cut the ortho-image into plot polygons and extract phenotypes for those plots into the database. The maximum size for each image is 200MB. The preferred upload format is PNG.</p>
25 <p><b>Example Data:</b> <a href="/static_content/imagebreed/AlfalfaExample35MeterMicasenseAerialDroneFlightRawCaptures.zip" download>Micasense 5 Band Raw Images (Unstitched image-captures) (Upload zipfile for ImageBreed to stitch.)</a></p>
26 <p><b>Example Data:</b> <a href="/static_content/imagebreed/ExampleAerialDroneFlightMicasensePanel.zip" download>Micasense 5 Band Panel Images (Micasense calibration panel images.) (Upload zipfile for ImageBreed to calibrate Micasense raw-captures during stitching.)</a></p>
27 <p><b>Example Data:</b> <a href="/static_content/imagebreed/AlfalfaExample35MeterMicasenseAerialDroneFlightOrthomosaics.zip" download>Micasense 5 Band Previously Stitched Orthophotomosaic Images (PNG Files in provided zipfile. Can upload each band separately into ImageBreed.)</a></p>
30 <button class="btn btn-primary" onclick="Workflow.complete(this); return false;">Go to Next Step</button>
33 <&| /util/workflow.mas:step, title=> "Field Trial" &>
34 <& /page/page_title.mas, title=>"Select your field trial" &>
36 <div class="form-group">
37 <label class="col-sm-3 control-label">Field Trial: </label>
38 <div class="col-sm-9" >
39 <div id="upload_drone_image_trial_select_div"></div>
44 <button class="btn btn-primary" id="upload_drone_image_field_trial_select_continue">Go to Next Step</button>
47 <&| /util/workflow.mas:step, title=> "Drone Run" &>
48 <& /page/page_title.mas, title=>"Select or create new drone run" &>
50 <table class="table table-bordered table-hover" id="drone_image_upload_drone_runs_table">
54 <th>Imaging Event Name</th>
55 <th>Imaging Event Type</th>
56 <th>Imaging Event Description</th>
57 <th>Imaging Event Date</th>
59 <th>Field Trial Name</th>
60 <th>Field Trial Description</th>
65 <!-- If drone run is selected above, the drone_run_project_id is passed to controller, negating need to create new drone run -->
66 <input id="drone_run_id" name="drone_run_id" type="hidden" value=""/>
69 <button class="btn btn-primary" id="drone_image_upload_create_drone_run">Create new drone run if not present in table</button>
73 <div id="drone_image_upload_create_drone_inputs" style="display:none">
74 <div class="form-group">
75 <label class="col-sm-3 control-label">Imaging Event Name: </label>
76 <div class="col-sm-9" >
77 <input class="form-control" id="drone_run_name" name="drone_run_name" type="text" />
80 <div class="form-group">
81 <label class="col-sm-3 control-label">Imaging Event Type:</label>
82 <div class="col-sm-9" >
83 <select class="form-control" id="drone_run_type" name="drone_run_type">
84 <option value="">Select One</option>
85 <option value="Aerial Medium to High Res">Medium to High Resolution Aerial Drone Image(s)</option>
86 <option value="Aerial Low Res">Low Resolution Aerial Drone Image(s)</option>
90 <div class="form-group">
91 <label class="col-sm-3 control-label">Camera Type:</label>
92 <div class="col-sm-9" >
93 <select class="form-control" id="drone_image_upload_camera_info" name="drone_image_upload_camera_info">
94 <option value="">Select One</option>
95 <option value="micasense_5">Micasense 5 Bands</option>
96 <option value="ccd_color">CCD Sensor Color Image</option>
97 <option value="cmos_color">CMOS Sensor Color Image</option>
101 <div class="form-group">
102 <label class="col-sm-3 control-label">Imaging Event Description: </label>
103 <div class="col-sm-9" >
104 <input class="form-control" id="drone_run_description" name="drone_run_description" type="text" />
107 <div class="form-group">
108 <label class="col-sm-3 control-label">Imaging Event Date:</label>
109 <div class="col-sm-9" >
110 <input class="form-control" id="drone_run_date" name="drone_run_date" title="drone_run_date" type="text" />
117 <button class="btn btn-primary" id="drone_image_upload_drone_run_continue">Go to Next Step</button>
120 <&| /util/workflow.mas:step, title=> "Image Info" &>
121 <& /page/page_title.mas, title=>"Stitched vs Unstitched and Number of Bands (Image Sets) To Upload" &>
125 <li>Raw images (unstitched) coming from your drone can be uploaded in a zip file. We can then stitch them together into an orthophotomosaic of the entire drone run.</li>
126 <li>Or you can choose to upload a single image and skip any stitching</li>
131 <li>It is possible to upload regular RGB or Black and White photos.</li>
132 <li>For multi-spectral cameras, it is possible to upload individual spectra orthomosaicphotos.</li>
133 <li>When uploading many separate bands of unstitched images, you will upload a single zipfile (.zip) which contains all images. In the zipfile each image is named following the template IMG_0001_1.tif, IMG_0001_2.tif, ..., IMG_0001_5.tif, ..., IMG_9999_5.tif. The final number represents the 5 bands coming from the camera, while the middle number is an index for the image capture. The middle number can be as many digits long as needed. The images should be in order in the zipfile. You will also need to upload a zipfile (.zip) containing the Micasense radiometrix calibration panel images, so that ImageBreed can produce the best orthomosaic possible.</li>
137 <div class="form-group">
138 <label class="col-sm-3 control-label">Do you require stitching an ortho image of the drone run:</label>
139 <div class="col-sm-9" >
140 <select class="form-control" id="drone_image_upload_drone_run_band_stitching" name="drone_image_upload_drone_run_band_stitching">
141 <option value="">Select One</option>
142 <option value="yes">Yes, I am uploading a zipfile of images to stitch</option>
143 <option value="no">No</option>
147 <div class="form-group" id="drone_run_upload_drone_run_band_number_div">
148 <label class="col-sm-3 control-label">Number of Spectral Bands (Image Sets) To Upload:</label>
149 <div class="col-sm-9" >
150 <select class="form-control" id="drone_run_band_number" name="drone_run_band_number">
151 <option value="">Select One</option>
152 <option value="one_bw">One Black and White Image</option>
153 <option value="one_rgb">One RGB Color Image</option>
154 <option value="1">One Spectral Band</option>
155 <option value="2">Two Separate Spectral Bands</option>
156 <option value="3">Three Separate Spectral Bands</option>
157 <option value="4">Four Separate Spectral Bands</option>
158 <option value="5">Five Separate Spectral Bands</option>
159 <option value="6">Six Separate Spectral Bands</option>
160 <option value="7">Seven Separate Spectral Bands</option>
166 <button class="btn btn-primary" id="drone_image_upload_drone_run_band_continue">Go to Next Step</button>
169 <&| /util/workflow.mas:step, title=> "Images" &>
170 <& /page/page_title.mas, title=>"Select Image(s) to Upload" &>
172 <div id="upload_drone_images_select_section">
176 <button type="button" class="btn btn-info" name="upload_drone_imagery_submit" id="upload_drone_imagery_submit">Submit</button>
182 <div id="upload_drone_imagery_verify_status"></div>
186 <div class="modal-footer">
187 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
195 <script defer="defer">
197 jQuery(document).ready(function() {
199 get_select_box('trials', 'upload_drone_image_trial_select_div', { 'name' : 'drone_run_field_trial_id', 'id' : 'drone_run_field_trial_id', 'empty':1, 'multiple':0 });
201 jQuery('#upload_drone_imagery_link').click( function() {
202 jQuery('#upload_drone_imagery_dialog').modal("show");
205 jQuery(document).on('change', '#drone_run_field_trial_id', function() {
206 var field_trial_id = jQuery(this).val();
207 jQuery('#drone_image_upload_drone_runs_table').DataTable({
209 ajax : '/api/drone_imagery/drone_runs?select_checkbox_name=upload_drone_imagery_drone_run_select&field_trial_id='+field_trial_id
213 jQuery('#upload_drone_image_field_trial_select_continue').click(function(){
214 if (jQuery('#drone_run_field_trial_id').val() == ''){
215 alert('Please select a field trial first');
217 Workflow.complete('#upload_drone_image_field_trial_select_continue');
218 Workflow.focus('#drone_imagery_upload_workflow', 2);
223 var drone_run_date_element = jQuery("#drone_run_date");
224 set_daterangepicker_default (drone_run_date_element);
225 jQuery('input[title="drone_run_date"]').daterangepicker(
227 "singleDatePicker": true,
228 "showDropdowns": true,
229 "autoUpdateInput": false,
232 drone_run_date_element.val(start.format('YYYY/MM/DD HH:mm:ss'));
236 jQuery('#drone_image_upload_create_drone_run').click(function(){
237 jQuery('#drone_image_upload_create_drone_inputs').show();
241 jQuery('#drone_image_upload_drone_run_band_stitching').change(function(){
242 if (jQuery('#drone_image_upload_drone_run_band_stitching').val() == 'yes') {
243 jQuery('#drone_run_upload_drone_run_band_number_div').hide();
245 jQuery('#drone_run_upload_drone_run_band_number_div').show();
249 jQuery('#drone_image_upload_drone_run_band_continue').click(function(){
251 var drone_run_band_number = jQuery('#drone_run_band_number').val();
252 var drone_run_band_unstitched = jQuery('#drone_image_upload_drone_run_band_stitching').val();
253 var drone_run_camera_info = jQuery('#drone_image_upload_camera_info').val();
254 var drone_run_id = jQuery('#drone_run_id').val();
255 if (drone_run_id != '' && drone_run_band_unstitched == 'yes') {
256 alert('Please create a new drone run band if you are uploading a zipfile of images to stitch.');
259 if (drone_run_band_unstitched == '') {
260 alert('Please select whether you are uploading unstitched images.');
263 if (drone_run_id == '' && drone_run_camera_info == '') {
264 alert('Please select the camera type used.');
269 if (drone_run_band_unstitched == 'no') {
270 if (drone_run_band_number == '') {
271 alert('Please select the number of drone run bands you will upload');
273 if (drone_run_band_number == 'one_bw' || drone_run_band_number == 'one_rgb') {
274 html = html + '<div class="well well-sm"><div class="form-group"><label class="col-sm-3 control-label">Drone Run Band Name: </label><div class="col-sm-9" ><input class="form-control" id="drone_run_band_name_1" name="drone_run_band_name_1" type="text" /></div></div><div class="form-group"><label class="col-sm-3 control-label">Drone Run Band Description: </label><div class="col-sm-9" ><input class="form-control" id="drone_run_band_description_1" name="drone_run_band_description_1" type="text" /></div></div><div class="form-group"><label class="col-sm-3 control-label">Drone Run Band Type:</label><div class="col-sm-9" ><select class="form-control" id="drone_run_band_type_1" name="drone_run_band_type_1"><option value="Black and White Image">Black and White Image</option><option value="RGB Color Image">RGB Color Image</option><option value="Blue (450-520nm)">Blue (450-520nm)</option><option value="Green (515-600nm)">Green (515-600nm)</option><option value="Red (600-690nm)">Red (600-690nm)</option><option value="Red Edge (690-750nm)">Red Edge (690-750nm)</option><option value="NIR (780-3000nm)">NIR (780-3000nm)</option><option value="MIR (3000-50000nm)">MIR (3000-50000nm)</option><option value="FIR (50000-1000000nm)">FIR (50000-1000000nm)</option><option value="Thermal IR (9000-14000nm)">Thermal IR (9000-14000nm)</option></select></div></div>';
275 html = html + '<div class="form-group"><label class="col-sm-3 control-label">Image: (.jpeg, .png)</label><div class="col-sm-9" ><input type="file" id="drone_run_band_stitched_ortho_image_1" name="drone_run_band_stitched_ortho_image_1" encoding="multipart/form-data" /></div></div>';
276 html = html + '</div>';
278 for (var i=0; i<drone_run_band_number; i++) {
279 html = html + '<div class="well well-sm"><div class="form-group"><label class="col-sm-3 control-label">Drone Run Band Name: </label><div class="col-sm-9" ><input class="form-control" id="drone_run_band_name_'+i+'" name="drone_run_band_name_'+i+'" type="text" /></div></div><div class="form-group"><label class="col-sm-3 control-label">Drone Run Band Description: </label><div class="col-sm-9" ><input class="form-control" id="drone_run_band_description_'+i+'" name="drone_run_band_description_'+i+'" type="text" /></div></div><div class="form-group"><label class="col-sm-3 control-label">Drone Run Band Type:</label><div class="col-sm-9" ><select class="form-control" id="drone_run_band_type_'+i+'" name="drone_run_band_type_'+i+'"><option value="Black and White Image">Black and White Image</option><option value="RGB Color Image">RGB Color Image</option><option value="Blue (450-520nm)">Blue (450-520nm)</option><option value="Green (515-600nm)">Green (515-600nm)</option><option value="Red (600-690nm)">Red (600-690nm)</option><option value="Red Edge (690-750nm)">Red Edge (690-750nm)</option><option value="NIR (780-3000nm)">NIR (780-3000nm)</option><option value="MIR (3000-50000nm)">MIR (3000-50000nm)</option><option value="FIR (50000-1000000nm)">FIR (50000-1000000nm)</option><option value="Thermal IR (9000-14000nm)">Thermal IR (9000-14000nm)</option></select></div></div>';
280 html = html + '<div class="form-group"><label class="col-sm-3 control-label">Image: (.jpeg, .png)</label><div class="col-sm-9" ><input type="file" id="drone_run_band_stitched_ortho_image_'+i+'" name="drone_run_band_stitched_ortho_image_'+i+'" encoding="multipart/form-data" /></div></div>';
281 html = html + '</div>';
286 else if (drone_run_band_unstitched == 'yes') {
287 html = html + '<div class="well well-sm">';
288 html = html + '<div class="form-group"><label class="col-sm-3 control-label">Drone Images ZipFile (.zip) (2GB Maximum): </label><div class="col-sm-9" ><input type="file" id="upload_drone_images_zipfile" name="upload_drone_images_zipfile" encoding="multipart/form-data" /></div></div>';
290 if (drone_run_camera_info == 'micasense_5') {
291 html = html + '<div class="form-group"><label class="col-sm-3 control-label">Micasense Radiometric Calibration Images ZipFile (.zip): </label><div class="col-sm-9" ><input type="file" id="upload_drone_images_panel_zipfile" name="upload_drone_images_panel_zipfile" encoding="multipart/form-data" /></div></div>';
294 html = html + '<div class="form-group"><label class="col-sm-3 control-label">Working Image Scale (Megapixels): </label><div class="col-sm-9" ><select class="form-control" id="upload_drone_images_stitching_work_pix" name="upload_drone_images_stitching_work_pix" disabled><option value="-1">Full</option><option value="0.6">0.6</option><option value="0.4">0.4</option><option value="1.0">1.0</option><option value="2.0">2.0</option></select></div></div>';
295 html = html + '</div>';
298 jQuery('#upload_drone_images_select_section').html(html);
299 Workflow.complete('#drone_image_upload_drone_run_band_continue');
300 Workflow.focus('#drone_imagery_upload_workflow', 4);
304 jQuery('#drone_image_upload_drone_run_continue').click(function(){
306 jQuery('input[name="upload_drone_imagery_drone_run_select"]:checked').each(function() {
307 selected.push(jQuery(this).val());
309 if (selected.length > 1){
310 alert('Only select one drone run!');
312 if (selected.length == 0 && jQuery('#drone_run_name').val() == ''){
313 alert('Select a drone run or create a new one!');
314 } else if (selected.length == 1 && jQuery('#drone_run_name').val() != ''){
315 alert('If you selected a drone run, do not try to make a new one at the same time!');
316 } else if (selected.length == 1 && jQuery('#drone_run_name').val() == ''){
317 jQuery('#drone_run_id').val(selected[0]);
318 Workflow.complete('#drone_image_upload_drone_run_continue');
319 Workflow.focus('#drone_imagery_upload_workflow', 3);
320 } else if (selected.length == 0 && jQuery('#drone_run_name').val() != '') {
321 if (jQuery('#drone_run_description').val() == ''){
322 alert('Please give a drone run description.');
323 } else if (jQuery('#drone_run_date').val() == ''){
324 alert('Please give a drone run date.');
325 } else if (jQuery('#drone_run_type') == ''){
326 alert('Please select a drone run type');
328 jQuery('#drone_run_id').val('');
330 url : '/api/drone_imagery/upload_drone_imagery_check_drone_name?drone_run_name='+jQuery('#drone_run_name').val(),
331 success: function(response){
332 console.log(response);
334 if (response.success) {
335 Workflow.complete('#drone_image_upload_drone_run_continue');
336 Workflow.focus('#drone_imagery_upload_workflow', 3);
338 else if (response.error) {
339 alert("Error: " + response.error);
343 error: function(response){
344 alert('Error checking drone run name!');
354 var drone_run_band_unstitched = '';
355 jQuery('#upload_drone_imagery_submit').click(function(){
356 var drone_run_band_number = jQuery('#drone_run_band_number').val();
357 drone_run_band_unstitched = jQuery('#drone_image_upload_drone_run_band_stitching').val();
358 var drone_run_camera_info = jQuery('#drone_image_upload_camera_info').val();
359 if (drone_run_band_unstitched == '') {
360 alert('Please select whether you are uploading unstitched images.');
363 if (drone_run_camera_info == '') {
364 alert('Please select the camera type used.');
368 if (drone_run_band_unstitched == 'no') {
369 if (drone_run_band_number == '') {
370 alert('Please select the number of drone run bands you will upload');
373 if (drone_run_band_number == 'one_bw' || drone_run_band_number == 'one_rgb') {
374 if (jQuery('#drone_run_band_name_1').val() == ''){
375 alert('Give a new drone run band name!');
377 } else if (jQuery('#drone_run_band_description_1').val() == ''){
378 alert('Please give a drone run band description.');
380 } else if (jQuery('#drone_run_band_type_1').val() == ''){
381 alert('Please select a drone run band type.');
384 if (jQuery('#drone_run_band_stitched_ortho_image_1').val() == '') {
385 alert('Please select an image');
389 for (var i=0; i<drone_run_band_number; i++) {
390 if (jQuery('#drone_run_band_name_'+i).val() == ''){
391 alert('Give a new drone run band name!');
393 } else if (jQuery('#drone_run_band_description_'+i).val() == ''){
394 alert('Please give a drone run band description.');
396 } else if (jQuery('#drone_run_band_type_'+i).val() == ''){
397 alert('Please select a drone run band type.');
400 if (jQuery('#drone_run_band_stitched_ortho_image_'+i).val() == '') {
401 alert('Please select an image');
407 } else if (drone_run_band_unstitched == 'yes') {
408 if (jQuery('#upload_drone_images_zipfile').val() == ''){
409 alert('Please select a zipfile of images');
412 // if (jQuery('#upload_drone_images_panel_zipfile').val() == ''){
413 // alert('Please select a zipfile of Micasense radiocalibration panel images');
418 upload_drone_imagery_form();
421 function upload_drone_imagery_form() {
422 jQuery('#upload_drone_imagery_form').attr("action", "/api/drone_imagery/upload_drone_imagery");
423 jQuery("#upload_drone_imagery_form").submit();
426 jQuery('#upload_drone_imagery_form').iframePostForm({
429 jQuery('#working_modal').modal("show");
430 if (drone_run_band_unstitched == 'yes') {
431 jQuery('#working_msg').html("It can take a very long time to assemble the orthophotomosaic depending on the number of images uploaded. Times range from 15 minutes to 5 days depending on the number of images, not including upload time.");
434 complete: function (response) {
435 console.log(response);
436 jQuery('#working_msg').html("");
438 jQuery('#working_modal').modal("hide");
439 if (response.error) {
440 alert(response.error);