GCC Code Coverage Report


Directory: src/athena/
File: athena_misc_ml.f90
Date: 2025-12-10 07:37:07
Exec Total Coverage
Lines: 1 1 100.0%
Functions: 0 0 -%
Branches: 59 82 72.0%

Line Branch Exec Source
1 module athena__misc_ml
2 !! Module containing miscellaneous machine learning procedures
3 !!
4 !! This module contains various procedures that are useful for machine
5 !! learning tasks. These include shuffling data, splitting data into
6 !! train and test sets, and padding data.
7 use coreutils, only: real32, stop_program
8 implicit none
9
10
11 private
12
13 public :: shuffle, split
14 public :: set_padding, pad_data
15
16
17 interface shuffle
18 !! Shuffle an array along one dimension
19 !!
20 !! This procedure shuffles an array along one dimension. The array
21 !! can be of any rank, but the dimension along which to shuffle must
22 !! be specified. An optional index array can also be shuffled.
23 procedure shuffle_1Dilist, &
24 shuffle_2Drdata, shuffle_3Didata, shuffle_3Drdata, &
25 shuffle_4Drdata, shuffle_5Drdata, &
26 shuffle_2Drdata_1Drlist, &
27 shuffle_3Didata_1Dilist, shuffle_3Didata_1Drlist, &
28 shuffle_4Drdata_1Dilist, shuffle_5Drdata_1Dilist, &
29 shuffle_5Drdata_1Drlist
30 end interface shuffle
31
32 interface split
33 !! Split an array into train and test sets
34 !!
35 !! This procedure splits an array into two sets along one dimension.
36 !! The array can be of any rank, but the dimension along which to
37 !! split must be specified. An optional index array can also be split.
38 !! The size of the left and right splits can also be specified. The
39 !! data can be shuffled before splitting.
40 procedure split_2Drdata_1Drlist, &
41 split_3Didata_1Dilist, split_3Didata_1Drlist, &
42 split_5Drdata, &
43 split_5Drdata_1Drlist
44 end interface split
45
46
47
48 contains
49 !###############################################################################
50 subroutine shuffle_1Dilist(data,seed)
51 !! Shuffle a 1D array along one dimension
52 implicit none
53
54 ! Arguments
55 integer, dimension(:), intent(inout) :: data
56 !! 1D array to be shuffled
57 integer, optional, intent(in) :: seed
58 !! Random seed
59
60 ! Local variables
61 integer :: itmp1, i, j
62 !! Loop indices
63 integer :: istart, num_data, seed_size
64 !! Start index, number of data points, seed size
65 real(real32) :: r
66 !! Random number
67 integer, allocatable, dimension(:) :: iseed
68 !! Random seed
69
70
71 ! Set or get random seed
72 !---------------------------------------------------------------------------
73 call random_seed(size=seed_size)
74 allocate(iseed(seed_size))
75 if(present(seed))then
76 iseed = seed
77 call random_seed(put=iseed)
78 else
79 call random_seed(get=iseed)
80 end if
81
82
83 ! Shuffle the data
84 !---------------------------------------------------------------------------
85 num_data = size(data,dim=1)
86 istart=1
87 do i=1,num_data
88 call random_number(r)
89 j = istart + floor((num_data+1-istart)*r)
90 if(i.eq.j) cycle
91 itmp1 = data(j)
92 data(j) = data(i)
93 data(i) = itmp1
94 end do
95
96 end subroutine shuffle_1Dilist
97 !-------------------------------------------------------------------------------
98 subroutine shuffle_2Drdata(data,dim,seed)
99 implicit none
100
101 ! Arguments
102 real(real32), dimension(:,:), intent(inout) :: data
103 !! 2D array to be shuffled
104 integer, optional, intent(in) :: seed
105 !! Random seed
106 integer, intent(in) :: dim
107 !! Dimension along which to shuffle
108
109 ! Local variables
110 integer :: istart,seed_size
111 !! Start index, seed size
112 integer :: i,j,n_data,iother
113 !! Loop indices, number of data points, other dimension
114 integer :: i1s,i2s,i1e,i2e,j1s,j2s,j1e,j2e
115 !! Start and end indices
116 real(real32) :: r
117 !! Random number
118 integer, allocatable, dimension(:) :: iseed
119 !! Random seed
120 real(real32), allocatable, dimension(:,:) :: tlist
121 !! Temporary list
122
123
124 ! Set or get random seed
125 !---------------------------------------------------------------------------
126 call random_seed(size=seed_size)
127 allocate(iseed(seed_size))
128 if(present(seed))then
129 iseed = seed
130 call random_seed(put=iseed)
131 else
132 call random_seed(get=iseed)
133 end if
134
135
136 ! Shuffle the data
137 !---------------------------------------------------------------------------
138 n_data = size(data,dim=dim)
139 if(dim.eq.1)then
140 iother = 2
141 i2s=1;i2e=size(data,dim=iother)
142 j2s=1;j2e=size(data,dim=iother)
143 else
144 iother = 1
145 i1s=1;i1e=size(data,dim=iother)
146 j1s=1;j1e=size(data,dim=iother)
147 end if
148 istart=1
149 allocate(tlist(1,size(data,dim=iother)))
150 do i=1,n_data
151 call random_number(r)
152 j = istart + floor((n_data+1-istart)*r)
153 if(i.eq.j) cycle
154 if(dim.eq.1)then
155 i1s=i;i1e=i
156 j1s=j;j1e=j
157 else
158 i2s=i;i2e=i
159 j2s=j;j2e=j
160 end if
161 tlist(1:1,:) = reshape(data(i1s:i1e,i2s:i2e),shape=shape(tlist))
162 data(i1s:i1e,i2s:i2e) = data(j1s:j1e,j2s:j2e)
163 data(j1s:j1e,j2s:j2e) = reshape(tlist(1:1,:),&
164 shape=shape(data(j1s:j1e,j2s:j2e)))
165 end do
166
167 end subroutine shuffle_2Drdata
168 !-------------------------------------------------------------------------------
169 subroutine shuffle_3Drdata(data,dim,seed)
170 !! Shuffle a 3D array along one dimension
171 implicit none
172
173 ! Arguments
174 real(real32), dimension(:,:,:), intent(inout) :: data
175 !! 3D array to be shuffled
176 integer, intent(in) :: dim
177 !! Dimension along which to shuffle
178 integer, optional, intent(in) :: seed
179 !! Random seed
180
181 ! Local variables
182 integer :: istart,seed_size
183 !! Start index, seed size
184 integer :: i,j,n_data
185 !! Loop indices, number of data points
186 real(real32) :: r
187 !! Random number
188 integer, dimension(3) :: idx_s,idx_e,jdx_s,jdx_e
189 !! Start and end indices
190 integer, dimension(3,2) :: t_size
191 !! Temporary size
192 integer, allocatable, dimension(:) :: iseed
193 !! Random seed
194 real(real32), allocatable, dimension(:,:,:) :: tlist
195 !! Temporary list
196
197
198 ! Set or get random seed
199 !---------------------------------------------------------------------------
200 call random_seed(size=seed_size)
201 allocate(iseed(seed_size))
202 if(present(seed))then
203 iseed = seed
204 call random_seed(put=iseed)
205 else
206 call random_seed(get=iseed)
207 end if
208
209 n_data = size(data,dim=dim)
210 do i=1,3
211 t_size(i,1) = 1
212 jdx_s(i) = 1
213 jdx_e(i) = size(data,dim=i)
214 idx_s(i) = 1
215 idx_e(i) = size(data,dim=i)
216 if(i.eq.dim) then
217 t_size(i,2) = 1
218 else
219 t_size(i,2) = size(data,dim=i)
220 end if
221 end do
222
223 allocate(tlist(t_size(1,2),t_size(2,2),t_size(3,2)))
224
225 istart=1
226 do i=1,n_data
227 call random_number(r)
228 j = istart + floor((n_data+1-istart)*r)
229 if(i.eq.j) cycle
230 idx_s(dim) = i
231 idx_e(dim) = i
232 jdx_s(dim) = j
233 jdx_e(dim) = j
234 tlist(&
235 t_size(1,1):t_size(1,2),&
236 t_size(2,1):t_size(2,2),&
237 t_size(3,1):t_size(3,2)) = data(&
238 idx_s(1):idx_e(1),&
239 idx_s(2):idx_e(2),&
240 idx_s(3):idx_e(3))
241 data(&
242 idx_s(1):idx_e(1),&
243 idx_s(2):idx_e(2),&
244 idx_s(3):idx_e(3)) = data(&
245 jdx_s(1):jdx_e(1),&
246 jdx_s(2):jdx_e(2),&
247 jdx_s(3):jdx_e(3))
248 data(&
249 jdx_s(1):jdx_e(1),&
250 jdx_s(2):jdx_e(2),&
251 jdx_s(3):jdx_e(3)) = tlist(&
252 t_size(1,1):t_size(1,2),&
253 t_size(2,1):t_size(2,2),&
254 t_size(3,1):t_size(3,2))
255 end do
256
257 end subroutine shuffle_3Drdata
258 !-------------------------------------------------------------------------------
259 subroutine shuffle_3Didata(data,dim,seed)
260 !! Shuffle a 3D array along one dimension
261 implicit none
262
263 ! Arguments
264 integer, dimension(:,:,:), intent(inout) :: data
265 !! 3D array to be shuffled
266 integer, intent(in) :: dim
267 !! Dimension along which to shuffle
268 integer, optional, intent(in) :: seed
269 !! Random seed
270
271 ! Local variables
272 integer :: istart,seed_size
273 !! Start index, seed size
274 integer :: i,j,n_data
275 !! Loop indices, number of data points
276 real(real32) :: r
277 !! Random number
278 integer, dimension(3) :: idx_s,idx_e,jdx_s,jdx_e
279 !! Start and end indices
280 integer, dimension(3,2) :: t_size
281 !! Temporary size
282 integer, allocatable, dimension(:) :: iseed
283 !! Random seed
284 integer, allocatable, dimension(:,:,:) :: tlist
285 !! Temporary list
286
287
288 ! Set or get random seed
289 !---------------------------------------------------------------------------
290 call random_seed(size=seed_size)
291 allocate(iseed(seed_size))
292 if(present(seed))then
293 iseed = seed
294 call random_seed(put=iseed)
295 else
296 call random_seed(get=iseed)
297 end if
298
299
300 ! Get the size of the data
301 !---------------------------------------------------------------------------
302 n_data = size(data,dim=dim)
303 do i=1,3
304 t_size(i,1) = 1
305 jdx_s(i) = 1
306 jdx_e(i) = size(data,dim=i)
307 idx_s(i) = 1
308 idx_e(i) = size(data,dim=i)
309 if(i.eq.dim) then
310 t_size(i,2) = 1
311 else
312 t_size(i,2) = size(data,dim=i)
313 end if
314 end do
315 allocate(tlist(t_size(1,2),t_size(2,2),t_size(3,2)))
316
317
318 ! Shuffle the data
319 !---------------------------------------------------------------------------
320 istart=1
321 do i=1,n_data
322 call random_number(r)
323 j = istart + floor((n_data+1-istart)*r)
324 if(i.eq.j) cycle
325 idx_s(dim) = i
326 idx_e(dim) = i
327 jdx_s(dim) = j
328 jdx_e(dim) = j
329 tlist(&
330 t_size(1,1):t_size(1,2),&
331 t_size(2,1):t_size(2,2),&
332 t_size(3,1):t_size(3,2)) = data(&
333 idx_s(1):idx_e(1),&
334 idx_s(2):idx_e(2),&
335 idx_s(3):idx_e(3))
336 data(&
337 idx_s(1):idx_e(1),&
338 idx_s(2):idx_e(2),&
339 idx_s(3):idx_e(3)) = data(&
340 jdx_s(1):jdx_e(1),&
341 jdx_s(2):jdx_e(2),&
342 jdx_s(3):jdx_e(3))
343 data(&
344 jdx_s(1):jdx_e(1),&
345 jdx_s(2):jdx_e(2),&
346 jdx_s(3):jdx_e(3)) = tlist(&
347 t_size(1,1):t_size(1,2),&
348 t_size(2,1):t_size(2,2),&
349 t_size(3,1):t_size(3,2))
350 end do
351
352 end subroutine shuffle_3Didata
353 !-------------------------------------------------------------------------------
354 subroutine shuffle_4Drdata(data,dim,seed)
355 !! Shuffle a 4D array along one dimension
356 implicit none
357
358 ! Arguments
359 real(real32), dimension(:,:,:,:), intent(inout) :: data
360 !! 4D array to be shuffled
361 integer, intent(in) :: dim
362 !! Dimension along which to shuffle
363 integer, optional, intent(in) :: seed
364 !! Random seed
365
366 ! Local variables
367 integer :: istart,seed_size
368 !! Start index, seed size
369 integer :: i,j,n_data
370 !! Loop indices, number of data points
371 real(real32) :: r
372 !! Random number
373 integer, dimension(4) :: idx_s,idx_e,jdx_s,jdx_e
374 !! Start and end indices
375 integer, dimension(4,2) :: t_size
376 !! Temporary size
377 integer, allocatable, dimension(:) :: iseed
378 !! Random seed
379 real(real32), allocatable, dimension(:,:,:,:) :: tlist
380 !! Temporary list
381
382
383 ! Set or get random seed
384 !---------------------------------------------------------------------------
385 call random_seed(size=seed_size)
386 allocate(iseed(seed_size))
387 if(present(seed))then
388 iseed = seed
389 call random_seed(put=iseed)
390 else
391 call random_seed(get=iseed)
392 end if
393
394
395 ! Get the size of the data
396 !---------------------------------------------------------------------------
397 n_data = size(data,dim=dim)
398 do i=1,4
399 t_size(i,1) = 1
400 jdx_s(i) = 1
401 jdx_e(i) = size(data,dim=i)
402 idx_s(i) = 1
403 idx_e(i) = size(data,dim=i)
404 if(i.eq.dim) then
405 t_size(i,2) = 1
406 else
407 t_size(i,2) = size(data,dim=i)
408 end if
409 end do
410 allocate(tlist(t_size(1,2),t_size(2,2),t_size(3,2),t_size(4,2)))
411
412
413 ! Shuffle the data
414 !---------------------------------------------------------------------------
415 istart=1
416 do i=1,n_data
417 call random_number(r)
418 j = istart + floor((n_data+1-istart)*r)
419 idx_s(dim) = i
420 idx_e(dim) = i
421 jdx_s(dim) = j
422 jdx_e(dim) = j
423 tlist(&
424 t_size(1,1):t_size(1,2),&
425 t_size(2,1):t_size(2,2),&
426 t_size(3,1):t_size(3,2),&
427 t_size(4,1):t_size(4,2)) = data(&
428 idx_s(1):idx_e(1),&
429 idx_s(2):idx_e(2),&
430 idx_s(3):idx_e(3),&
431 idx_s(4):idx_e(4))
432 data(&
433 idx_s(1):idx_e(1),&
434 idx_s(2):idx_e(2),&
435 idx_s(3):idx_e(3),&
436 idx_s(4):idx_e(4)) = data(&
437 jdx_s(1):jdx_e(1),&
438 jdx_s(2):jdx_e(2),&
439 jdx_s(3):jdx_e(3),&
440 jdx_s(4):jdx_e(4))
441 data(&
442 jdx_s(1):jdx_e(1),&
443 jdx_s(2):jdx_e(2),&
444 jdx_s(3):jdx_e(3),&
445 jdx_s(4):jdx_e(4)) = tlist(&
446 t_size(1,1):t_size(1,2),&
447 t_size(2,1):t_size(2,2),&
448 t_size(3,1):t_size(3,2),&
449 t_size(4,1):t_size(4,2))
450 end do
451
452 end subroutine shuffle_4Drdata
453 !-------------------------------------------------------------------------------
454 subroutine shuffle_5Drdata(data,dim,seed)
455 !! Shuffle a 5D array along one dimension
456 implicit none
457
458 ! Arguments
459 real(real32), dimension(:,:,:,:,:), intent(inout) :: data
460 !! 5D array to be shuffled
461 integer, intent(in) :: dim
462 !! Dimension along which to shuffle
463 integer, optional, intent(in) :: seed
464 !! Random seed
465
466 ! Local variables
467 integer :: istart,seed_size
468 !! Start index, seed size
469 integer :: i,j,n_data
470 !! Loop indices, number of data points
471 real(real32) :: r
472 !! Random number
473 integer, dimension(5) :: idx_s,idx_e,jdx_s,jdx_e
474 !! Start and end indices
475 integer, dimension(5,2) :: t_size
476 !! Temporary size
477 integer, allocatable, dimension(:) :: iseed
478 !! Random seed
479 real(real32), allocatable, dimension(:,:,:,:,:) :: tlist
480 !! Temporary list
481
482
483 ! Set or get random seed
484 !---------------------------------------------------------------------------
485 call random_seed(size=seed_size)
486 allocate(iseed(seed_size))
487 if(present(seed))then
488 iseed = seed
489 call random_seed(put=iseed)
490 else
491 call random_seed(get=iseed)
492 end if
493
494
495 ! Get the size of the data
496 !---------------------------------------------------------------------------
497 n_data = size(data,dim=dim)
498 do i=1,5
499 t_size(i,1) = 1
500 jdx_s(i) = 1
501 jdx_e(i) = size(data,dim=i)
502 idx_s(i) = 1
503 idx_e(i) = size(data,dim=i)
504 if(i.eq.dim) then
505 t_size(i,2) = 1
506 else
507 t_size(i,2) = size(data,dim=i)
508 end if
509 end do
510 allocate(tlist(&
511 t_size(1,2),t_size(2,2),&
512 t_size(3,2),t_size(4,2),&
513 t_size(5,2)))
514
515
516 ! Shuffle the data
517 !---------------------------------------------------------------------------
518 istart=1
519 do i=1,n_data
520 call random_number(r)
521 j = istart + floor((n_data+1-istart)*r)
522 idx_s(dim) = i
523 idx_e(dim) = i
524 jdx_s(dim) = j
525 jdx_e(dim) = j
526 tlist(&
527 t_size(1,1):t_size(1,2),&
528 t_size(2,1):t_size(2,2),&
529 t_size(3,1):t_size(3,2),&
530 t_size(4,1):t_size(4,2),&
531 t_size(5,1):t_size(5,2)) = data(&
532 idx_s(1):idx_e(1),&
533 idx_s(2):idx_e(2),&
534 idx_s(3):idx_e(3),&
535 idx_s(4):idx_e(4),&
536 idx_s(5):idx_e(5))
537 data(&
538 idx_s(1):idx_e(1),&
539 idx_s(2):idx_e(2),&
540 idx_s(3):idx_e(3),&
541 idx_s(4):idx_e(4),&
542 idx_s(5):idx_e(5)) = data(&
543 jdx_s(1):jdx_e(1),&
544 jdx_s(2):jdx_e(2),&
545 jdx_s(3):jdx_e(3),&
546 jdx_s(4):jdx_e(4),&
547 jdx_s(5):jdx_e(5))
548 data(&
549 jdx_s(1):jdx_e(1),&
550 jdx_s(2):jdx_e(2),&
551 jdx_s(3):jdx_e(3),&
552 jdx_s(4):jdx_e(4),&
553 jdx_s(5):jdx_e(5)) = tlist(&
554 t_size(1,1):t_size(1,2),&
555 t_size(2,1):t_size(2,2),&
556 t_size(3,1):t_size(3,2),&
557 t_size(4,1):t_size(4,2),&
558 t_size(5,1):t_size(5,2))
559 end do
560
561 end subroutine shuffle_5Drdata
562 !-------------------------------------------------------------------------------
563 subroutine shuffle_2Drdata_1Drlist(data,label,dim,seed,shuffle_list)
564 !! Shuffle a 2D array along one dimension
565 implicit none
566
567 ! Arguments
568 real(real32), dimension(:,:), intent(inout) :: data
569 !! 2D array to be shuffled
570 real(real32), dimension(:), intent(inout) :: label
571 !! 1D array to be shuffled
572 integer, intent(in) :: dim
573 !! Dimension along which to shuffle
574 integer, optional, intent(in) :: seed
575 !! Random seed
576 integer, optional, dimension(size(data,dim)), intent(out) :: shuffle_list
577 !! Index array
578
579 ! Local variables
580 integer :: istart,seed_size
581 !! Start index, seed size
582 integer :: i,j,n_data
583 !! Loop indices, number of data points
584 real(real32) :: rtmp1
585 !! Temporary real
586 real(real32) :: r
587 !! Random number
588 integer, dimension(2) :: idx_s,idx_e,jdx_s,jdx_e
589 !! Start and end indices
590 integer, dimension(2,2) :: t_size
591 !! Temporary size
592 integer, allocatable, dimension(:) :: iseed
593 !! Random seed
594 real(real32), allocatable, dimension(:,:) :: tlist
595 !! Temporary list
596
597
598 ! Set or get random seed
599 !---------------------------------------------------------------------------
600 call random_seed(size=seed_size)
601 allocate(iseed(seed_size))
602 if(present(seed))then
603 iseed = seed
604 call random_seed(put=iseed)
605 else
606 call random_seed(get=iseed)
607 end if
608
609
610 ! Get the size of the data
611 !---------------------------------------------------------------------------
612 n_data = size(data,dim=dim)
613 do i=1,2
614 t_size(i,1) = 1
615 jdx_s(i) = 1
616 jdx_e(i) = size(data,dim=i)
617 idx_s(i) = 1
618 idx_e(i) = size(data,dim=i)
619 if(i.eq.dim) then
620 t_size(i,2) = 1
621 else
622 t_size(i,2) = size(data,dim=i)
623 end if
624 end do
625
626 allocate(tlist(t_size(1,2),t_size(2,2)))
627
628 istart=1
629 do i=1,n_data
630 call random_number(r)
631 j = istart + floor((n_data+1-istart)*r)
632 if(present(shuffle_list)) shuffle_list(i) = j
633 idx_s(dim) = i
634 idx_e(dim) = i
635 jdx_s(dim) = j
636 jdx_e(dim) = j
637 tlist(&
638 t_size(1,1):t_size(1,2),&
639 t_size(2,1):t_size(2,2)) = data(&
640 idx_s(1):idx_e(1),&
641 idx_s(2):idx_e(2))
642 data(&
643 idx_s(1):idx_e(1),&
644 idx_s(2):idx_e(2)) = data(&
645 jdx_s(1):jdx_e(1),&
646 jdx_s(2):jdx_e(2))
647 data(&
648 jdx_s(1):jdx_e(1),&
649 jdx_s(2):jdx_e(2)) = tlist(&
650 t_size(1,1):t_size(1,2),&
651 t_size(2,1):t_size(2,2))
652
653 rtmp1 = label(i)
654 label(i) = label(j)
655 label(j) = rtmp1
656 end do
657
658 end subroutine shuffle_2Drdata_1Drlist
659 !-------------------------------------------------------------------------------
660 subroutine shuffle_3Didata_1Dilist(data,label,dim,seed)
661 !! Shuffle a 3D array along one dimension
662 implicit none
663
664 ! Arguments
665 integer, dimension(:,:,:), intent(inout) :: data
666 !! 3D array to be shuffled
667 integer, dimension(:), intent(inout) :: label
668 !! 1D array to be shuffled
669 integer, intent(in) :: dim
670 !! Dimension along which to shuffle
671 integer, optional, intent(in) :: seed
672 !! Random seed
673
674 ! Local variables
675 integer :: istart,seed_size
676 !! Start index, seed size
677 integer :: i,j,n_data
678 !! Loop indices, number of data points
679 integer :: itmp1
680 !! Temporary integer
681 real(real32) :: r
682 !! Random number
683 integer, dimension(3) :: idx_s,idx_e,jdx_s,jdx_e
684 !! Start and end indices
685 integer, dimension(3,2) :: t_size
686 !! Temporary size
687 integer, allocatable, dimension(:) :: iseed
688 !! Random seed
689 integer, allocatable, dimension(:,:,:) :: tlist
690 !! Temporary list
691
692
693 ! Set or get random seed
694 !---------------------------------------------------------------------------
695 call random_seed(size=seed_size)
696 allocate(iseed(seed_size))
697 if(present(seed))then
698 iseed = seed
699 call random_seed(put=iseed)
700 else
701 call random_seed(get=iseed)
702 end if
703
704
705 ! Get the size of the data
706 !---------------------------------------------------------------------------
707 n_data = size(data,dim=dim)
708 do i=1,3
709 t_size(i,1) = 1
710 jdx_s(i) = 1
711 jdx_e(i) = size(data,dim=i)
712 idx_s(i) = 1
713 idx_e(i) = size(data,dim=i)
714 if(i.eq.dim) then
715 t_size(i,2) = 1
716 else
717 t_size(i,2) = size(data,dim=i)
718 end if
719 end do
720 allocate(tlist(t_size(1,2),t_size(2,2),t_size(3,2)))
721
722
723 ! Shuffle the data
724 !---------------------------------------------------------------------------
725 istart=1
726 do i=1,n_data
727 call random_number(r)
728 j = istart + floor((n_data+1-istart)*r)
729 idx_s(dim) = i
730 idx_e(dim) = i
731 jdx_s(dim) = j
732 jdx_e(dim) = j
733 tlist(&
734 t_size(1,1):t_size(1,2),&
735 t_size(2,1):t_size(2,2),&
736 t_size(3,1):t_size(3,2)) = data(&
737 idx_s(1):idx_e(1),&
738 idx_s(2):idx_e(2),&
739 idx_s(3):idx_e(3))
740 data(&
741 idx_s(1):idx_e(1),&
742 idx_s(2):idx_e(2),&
743 idx_s(3):idx_e(3)) = data(&
744 jdx_s(1):jdx_e(1),&
745 jdx_s(2):jdx_e(2),&
746 jdx_s(3):jdx_e(3))
747 data(&
748 jdx_s(1):jdx_e(1),&
749 jdx_s(2):jdx_e(2),&
750 jdx_s(3):jdx_e(3)) = tlist(&
751 t_size(1,1):t_size(1,2),&
752 t_size(2,1):t_size(2,2),&
753 t_size(3,1):t_size(3,2))
754 itmp1 = label(i)
755 label(i) = label(j)
756 label(j) = itmp1
757 end do
758
759 end subroutine shuffle_3Didata_1Dilist
760 !-------------------------------------------------------------------------------
761 subroutine shuffle_3Didata_1Drlist(data,label,dim,seed)
762 !! Shuffle a 3D array along one dimension
763 implicit none
764
765 ! Arguments
766 integer, dimension(:,:,:), intent(inout) :: data
767 !! 3D array to be shuffled
768 real(real32), dimension(:), intent(inout) :: label
769 !! 1D array to be shuffled
770 integer, intent(in) :: dim
771 !! Dimension along which to shuffle
772 integer, optional, intent(in) :: seed
773 !! Random seed
774
775 ! Local variables
776 integer :: istart,seed_size
777 !! Start index, seed size
778 integer :: i,j,n_data
779 !! Loop indices, number of data points
780 integer :: itmp1
781 !! Temporary integer
782 real(real32) :: r
783 !! Random number
784 integer, dimension(3) :: idx_s,idx_e,jdx_s,jdx_e
785 !! Start and end indices
786 integer, dimension(3,2) :: t_size
787 !! Temporary size
788 integer, allocatable, dimension(:) :: iseed
789 !! Random seed
790 integer, allocatable, dimension(:,:,:) :: tlist
791 !! Temporary list
792
793
794 ! Set or get random seed
795 !---------------------------------------------------------------------------
796 call random_seed(size=seed_size)
797 allocate(iseed(seed_size))
798 if(present(seed))then
799 iseed = seed
800 call random_seed(put=iseed)
801 else
802 call random_seed(get=iseed)
803 end if
804
805
806 ! Get the size of the data
807 !---------------------------------------------------------------------------
808 n_data = size(data,dim=dim)
809 do i=1,3
810 t_size(i,1) = 1
811 jdx_s(i) = 1
812 jdx_e(i) = size(data,dim=i)
813 idx_s(i) = 1
814 idx_e(i) = size(data,dim=i)
815 if(i.eq.dim) then
816 t_size(i,2) = 1
817 else
818 t_size(i,2) = size(data,dim=i)
819 end if
820 end do
821 allocate(tlist(t_size(1,2),t_size(2,2),t_size(3,2)))
822
823
824 ! Shuffle the data
825 !---------------------------------------------------------------------------
826 istart=1
827 do i=1,n_data
828 call random_number(r)
829 j = istart + floor((n_data+1-istart)*r)
830 idx_s(dim) = i
831 idx_e(dim) = i
832 jdx_s(dim) = j
833 jdx_e(dim) = j
834 tlist(&
835 t_size(1,1):t_size(1,2),&
836 t_size(2,1):t_size(2,2),&
837 t_size(3,1):t_size(3,2)) = data(&
838 idx_s(1):idx_e(1),&
839 idx_s(2):idx_e(2),&
840 idx_s(3):idx_e(3))
841 data(&
842 idx_s(1):idx_e(1),&
843 idx_s(2):idx_e(2),&
844 idx_s(3):idx_e(3)) = data(&
845 jdx_s(1):jdx_e(1),&
846 jdx_s(2):jdx_e(2),&
847 jdx_s(3):jdx_e(3))
848 data(&
849 jdx_s(1):jdx_e(1),&
850 jdx_s(2):jdx_e(2),&
851 jdx_s(3):jdx_e(3)) = tlist(&
852 t_size(1,1):t_size(1,2),&
853 t_size(2,1):t_size(2,2),&
854 t_size(3,1):t_size(3,2))
855 itmp1 = label(i)
856 label(i) = label(j)
857 label(j) = itmp1
858 end do
859
860 end subroutine shuffle_3Didata_1Drlist
861 !-------------------------------------------------------------------------------
862 subroutine shuffle_4Drdata_1Dilist(data,label,dim,seed)
863 !! Shuffle a 4D array along one dimension
864 implicit none
865
866 ! Arguments
867 real(real32), dimension(:,:,:,:), intent(inout) :: data
868 !! 4D array to be shuffled
869 integer, dimension(:), intent(inout) :: label
870 !! 1D array to be shuffled
871 integer, intent(in) :: dim
872 !! Dimension along which to shuffle
873 integer, optional, intent(in) :: seed
874 !! Random seed
875
876 ! Local variables
877 integer :: istart, seed_size
878 !! Start index, seed size
879 integer :: i,j,n_data
880 !! Loop indices, number of data points
881 integer :: itmp1
882 !! Temporary integer
883 real(real32) :: r
884 !! Random number
885 integer, dimension(4) :: idx_s,idx_e,jdx_s,jdx_e
886 !! Start and end indices
887 integer, dimension(4,2) :: t_size
888 !! Temporary size
889 integer, allocatable, dimension(:) :: iseed
890 !! Random seed
891 real(real32), allocatable, dimension(:,:,:,:) :: tlist
892 !! Temporary list
893
894
895
896 ! Set or get random seed
897 !---------------------------------------------------------------------------
898 call random_seed(size=seed_size)
899 allocate(iseed(seed_size))
900 if(present(seed))then
901 iseed = seed
902 call random_seed(put=iseed)
903 else
904 call random_seed(get=iseed)
905 end if
906
907
908 ! Get the size of the data
909 !---------------------------------------------------------------------------
910 n_data = size(data,dim=dim)
911 do i=1,4
912 t_size(i,1) = 1
913 jdx_s(i) = 1
914 jdx_e(i) = size(data,dim=i)
915 idx_s(i) = 1
916 idx_e(i) = size(data,dim=i)
917 if(i.eq.dim) then
918 t_size(i,2) = 1
919 else
920 t_size(i,2) = size(data,dim=i)
921 end if
922 end do
923 allocate(tlist(t_size(1,2),t_size(2,2),t_size(3,2),t_size(4,2)))
924
925
926 ! Shuffle the data
927 !---------------------------------------------------------------------------
928 istart=1
929 do i=1,n_data
930 call random_number(r)
931 j = istart + floor((n_data+1-istart)*r)
932 idx_s(dim) = i
933 idx_e(dim) = i
934 jdx_s(dim) = j
935 jdx_e(dim) = j
936 tlist(&
937 t_size(1,1):t_size(1,2),&
938 t_size(2,1):t_size(2,2),&
939 t_size(3,1):t_size(3,2),&
940 t_size(4,1):t_size(4,2)) = data(&
941 idx_s(1):idx_e(1),&
942 idx_s(2):idx_e(2),&
943 idx_s(3):idx_e(3),&
944 idx_s(4):idx_e(4))
945 data(&
946 idx_s(1):idx_e(1),&
947 idx_s(2):idx_e(2),&
948 idx_s(3):idx_e(3),&
949 idx_s(4):idx_e(4)) = data(&
950 jdx_s(1):jdx_e(1),&
951 jdx_s(2):jdx_e(2),&
952 jdx_s(3):jdx_e(3),&
953 jdx_s(4):jdx_e(4))
954 data(&
955 jdx_s(1):jdx_e(1),&
956 jdx_s(2):jdx_e(2),&
957 jdx_s(3):jdx_e(3),&
958 jdx_s(4):jdx_e(4)) = tlist(&
959 t_size(1,1):t_size(1,2),&
960 t_size(2,1):t_size(2,2),&
961 t_size(3,1):t_size(3,2),&
962 t_size(4,1):t_size(4,2))
963 itmp1 = label(i)
964 label(i) = label(j)
965 label(j) = itmp1
966 end do
967
968 end subroutine shuffle_4Drdata_1Dilist
969 !-------------------------------------------------------------------------------
970 subroutine shuffle_5Drdata_1Dilist(data,label,dim,seed)
971 !! Shuffle a 5D array along one dimension
972 implicit none
973
974 ! Arguments
975 real(real32), dimension(:,:,:,:,:), intent(inout) :: data
976 !! 5D array to be shuffled
977 integer, dimension(:), intent(inout) :: label
978 !! 1D array to be shuffled
979 integer, intent(in) :: dim
980 !! Dimension along which to shuffle
981 integer, optional, intent(in) :: seed
982 !! Random seed
983
984 ! Local variables
985 integer :: istart,seed_size
986 !! Start index, seed size
987 integer :: i,j,n_data
988 !! Loop indices, number of data points
989 integer :: itmp1
990 !! Temporary integer
991 real(real32) :: r
992 !! Random number
993 integer, dimension(5) :: idx_s,idx_e,jdx_s,jdx_e
994 !! Start and end indices
995 integer, dimension(5,2) :: t_size
996 !! Temporary size
997 integer, allocatable, dimension(:) :: iseed
998 !! Random seed
999 real(real32), allocatable, dimension(:,:,:,:,:) :: tlist
1000 !! Temporary list
1001
1002
1003 ! Set or get random seed
1004 !---------------------------------------------------------------------------
1005 call random_seed(size=seed_size)
1006 allocate(iseed(seed_size))
1007 if(present(seed))then
1008 iseed = seed
1009 call random_seed(put=iseed)
1010 else
1011 call random_seed(get=iseed)
1012 end if
1013
1014
1015 ! Get the size of the data
1016 !---------------------------------------------------------------------------
1017 n_data = size(data,dim=dim)
1018 do i=1,5
1019 t_size(i,1) = 1
1020 jdx_s(i) = 1
1021 jdx_e(i) = size(data,dim=i)
1022 idx_s(i) = 1
1023 idx_e(i) = size(data,dim=i)
1024 if(i.eq.dim) then
1025 t_size(i,2) = 1
1026 else
1027 t_size(i,2) = size(data,dim=i)
1028 end if
1029 end do
1030 allocate(tlist(&
1031 t_size(1,2),t_size(2,2),&
1032 t_size(3,2),t_size(4,2),&
1033 t_size(5,2)))
1034
1035
1036 ! Shuffle the data
1037 !---------------------------------------------------------------------------
1038 istart=1
1039 do i=1,n_data
1040 call random_number(r)
1041 j = istart + floor((n_data+1-istart)*r)
1042 idx_s(dim) = i
1043 idx_e(dim) = i
1044 jdx_s(dim) = j
1045 jdx_e(dim) = j
1046 tlist(&
1047 t_size(1,1):t_size(1,2),&
1048 t_size(2,1):t_size(2,2),&
1049 t_size(3,1):t_size(3,2),&
1050 t_size(4,1):t_size(4,2),&
1051 t_size(5,1):t_size(5,2)) = data(&
1052 idx_s(1):idx_e(1),&
1053 idx_s(2):idx_e(2),&
1054 idx_s(3):idx_e(3),&
1055 idx_s(4):idx_e(4),&
1056 idx_s(5):idx_e(5))
1057 data(&
1058 idx_s(1):idx_e(1),&
1059 idx_s(2):idx_e(2),&
1060 idx_s(3):idx_e(3),&
1061 idx_s(4):idx_e(4),&
1062 idx_s(5):idx_e(5)) = data(&
1063 jdx_s(1):jdx_e(1),&
1064 jdx_s(2):jdx_e(2),&
1065 jdx_s(3):jdx_e(3),&
1066 jdx_s(4):jdx_e(4),&
1067 jdx_s(5):jdx_e(5))
1068 data(&
1069 jdx_s(1):jdx_e(1),&
1070 jdx_s(2):jdx_e(2),&
1071 jdx_s(3):jdx_e(3),&
1072 jdx_s(4):jdx_e(4),&
1073 jdx_s(5):jdx_e(5)) = tlist(&
1074 t_size(1,1):t_size(1,2),&
1075 t_size(2,1):t_size(2,2),&
1076 t_size(3,1):t_size(3,2),&
1077 t_size(4,1):t_size(4,2),&
1078 t_size(5,1):t_size(5,2))
1079 itmp1 = label(i)
1080 label(i) = label(j)
1081 label(j) = itmp1
1082 end do
1083
1084 end subroutine shuffle_5Drdata_1Dilist
1085 !-------------------------------------------------------------------------------
1086 subroutine shuffle_5Drdata_1Drlist(data,label,dim,seed,shuffle_list)
1087 !! Shuffle a 5D array along one dimension
1088 implicit none
1089
1090 ! Arguments
1091 real(real32), dimension(:,:,:,:,:), intent(inout) :: data
1092 !! 5D array to be shuffled
1093 real(real32), dimension(:), intent(inout) :: label
1094 !! 1D array to be shuffled
1095 integer, intent(in) :: dim
1096 !! Dimension along which to shuffle
1097 integer, optional, intent(in) :: seed
1098 !! Random seed
1099 integer, optional, dimension(size(data,dim)), intent(out) :: shuffle_list
1100 !! Index array
1101
1102 ! Local variables
1103 integer :: istart,seed_size
1104 !! Start index, seed size
1105 integer :: i,j,n_data
1106 !! Loop indices, number of data points
1107 real(real32) :: rtmp1
1108 !! Temporary real
1109 real(real32) :: r
1110 !! Random number
1111 integer, dimension(5) :: idx_s,idx_e,jdx_s,jdx_e
1112 !! Start and end indices
1113 integer, dimension(5,2) :: t_size
1114 !! Temporary size
1115 integer, allocatable, dimension(:) :: iseed
1116 !! Random seed
1117 real(real32), allocatable, dimension(:,:,:,:,:) :: tlist
1118 !! Temporary list
1119
1120
1121 ! Set or get random seed
1122 !---------------------------------------------------------------------------
1123 call random_seed(size=seed_size)
1124 allocate(iseed(seed_size))
1125 if(present(seed))then
1126 iseed = seed
1127 call random_seed(put=iseed)
1128 else
1129 call random_seed(get=iseed)
1130 end if
1131
1132
1133 ! Get the size of the data
1134 !---------------------------------------------------------------------------
1135 n_data = size(data,dim=dim)
1136 do i=1,5
1137 t_size(i,1) = 1
1138 jdx_s(i) = 1
1139 jdx_e(i) = size(data,dim=i)
1140 idx_s(i) = 1
1141 idx_e(i) = size(data,dim=i)
1142 if(i.eq.dim) then
1143 t_size(i,2) = 1
1144 else
1145 t_size(i,2) = size(data,dim=i)
1146 end if
1147 end do
1148
1149 allocate(tlist(&
1150 t_size(1,2),t_size(2,2),&
1151 t_size(3,2),t_size(4,2),&
1152 t_size(5,2)))
1153
1154 istart=1
1155 do i=1,n_data
1156 call random_number(r)
1157 j = istart + floor((n_data+1-istart)*r)
1158 if(present(shuffle_list)) shuffle_list(i) = j
1159 idx_s(dim) = i
1160 idx_e(dim) = i
1161 jdx_s(dim) = j
1162 jdx_e(dim) = j
1163 tlist(&
1164 t_size(1,1):t_size(1,2),&
1165 t_size(2,1):t_size(2,2),&
1166 t_size(3,1):t_size(3,2),&
1167 t_size(4,1):t_size(4,2),&
1168 t_size(5,1):t_size(5,2)) = data(&
1169 idx_s(1):idx_e(1),&
1170 idx_s(2):idx_e(2),&
1171 idx_s(3):idx_e(3),&
1172 idx_s(4):idx_e(4),&
1173 idx_s(5):idx_e(5))
1174 data(&
1175 idx_s(1):idx_e(1),&
1176 idx_s(2):idx_e(2),&
1177 idx_s(3):idx_e(3),&
1178 idx_s(4):idx_e(4),&
1179 idx_s(5):idx_e(5)) = data(&
1180 jdx_s(1):jdx_e(1),&
1181 jdx_s(2):jdx_e(2),&
1182 jdx_s(3):jdx_e(3),&
1183 jdx_s(4):jdx_e(4),&
1184 jdx_s(5):jdx_e(5))
1185 data(&
1186 jdx_s(1):jdx_e(1),&
1187 jdx_s(2):jdx_e(2),&
1188 jdx_s(3):jdx_e(3),&
1189 jdx_s(4):jdx_e(4),&
1190 jdx_s(5):jdx_e(5)) = tlist(&
1191 t_size(1,1):t_size(1,2),&
1192 t_size(2,1):t_size(2,2),&
1193 t_size(3,1):t_size(3,2),&
1194 t_size(4,1):t_size(4,2),&
1195 t_size(5,1):t_size(5,2))
1196 rtmp1 = label(i)
1197 label(i) = label(j)
1198 label(j) = rtmp1
1199 end do
1200
1201 end subroutine shuffle_5Drdata_1Drlist
1202 !###############################################################################
1203
1204
1205 !##############################################################################!
1206 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
1207 !##############################################################################!
1208
1209
1210 !###############################################################################
1211 subroutine split_5Drdata( &
1212 data, left, right, dim, &
1213 left_size, right_size, &
1214 shuffle, seed &
1215 )
1216 !! Split a 5D array along one dimension
1217 implicit none
1218
1219 ! Arguments
1220 real(real32), dimension(:,:,:,:,:), intent(in) :: data
1221 !! 5D array to be split
1222 real(real32), allocatable, dimension(:,:,:,:,:), intent(out) :: left, right
1223 !! 5D arrays to store the left and right splits
1224 integer, intent(in) :: dim
1225 !! Dimension along which to split
1226 real(real32), optional, intent(in) :: left_size, right_size
1227 !! Size of the left and right splits
1228 logical, optional, intent(in) :: shuffle
1229 !! Shuffle the data before splitting
1230 integer, optional, intent(in) :: seed
1231 !! Random seed
1232
1233 ! Local variables
1234 integer :: seed_, left_num_, right_num_
1235 !! Random seed, number of elements in left and right splits
1236 logical :: shuffle_
1237 !! Shuffle flag
1238 integer :: i, j
1239 !! Loop indices
1240 integer :: num_redos
1241 !! Number of redos
1242 real(real32) :: rtmp1
1243 !! Temporary real
1244 integer, allocatable, dimension(:) :: indices_l, indices_r
1245 !! Index arrays
1246 real(real32), allocatable, dimension(:) :: tlist
1247 !! Temporary list
1248 real(real32), allocatable, dimension(:,:,:,:,:) :: data_copy
1249 !! Copy of the input data
1250
1251 type :: idx_type
1252 !! Type for index array
1253 integer, allocatable, dimension(:) :: loc
1254 !! Index array
1255 end type idx_type
1256 type(idx_type), dimension(5) :: idx
1257 !! Index array
1258
1259
1260 ! Determine number of elements for left and right split
1261 !---------------------------------------------------------------------------
1262 if(.not.present(left_size).and..not.present(right_size))then
1263 call stop_program("neither left_size nor right_size provided to split. &
1264 &Expected at least one." &
1265 )
1266 return
1267 elseif(present(left_size).and..not.present(right_size))then
1268 left_num_ = nint(left_size*size(data,dim))
1269 right_num_ = size(data,dim) - left_num_
1270 elseif(.not.present(left_size).and.present(right_size))then
1271 right_num_ = nint(right_size*size(data,dim))
1272 left_num_ = size(data,dim) - right_num_
1273 else
1274 left_num_ = nint(left_size*size(data,dim))
1275 right_num_ = nint(right_size*size(data,dim))
1276 if(left_num_ + right_num_ .ne. size(data,dim)) &
1277 right_num_ = size(data,dim) - left_num_
1278 end if
1279
1280
1281 ! Initialies optional arguments
1282 !---------------------------------------------------------------------------
1283 if(present(shuffle))then
1284 shuffle_ = shuffle
1285 else
1286 shuffle_ = .false.
1287 end if
1288
1289 if(present(seed))then
1290 seed_ = seed
1291 else
1292 call system_clock(count=seed_)
1293 end if
1294
1295
1296 ! Copy input data
1297 !---------------------------------------------------------------------------
1298 data_copy = data
1299 if(shuffle_) call shuffle_5Drdata(data_copy,dim,seed_)
1300
1301
1302 ! Get list of indices for right split
1303 !---------------------------------------------------------------------------
1304 num_redos = 0
1305 allocate(tlist(right_num_))
1306 call random_number(tlist)
1307 indices_r = floor(tlist*size(data,dim)) + 1
1308 i = 1
1309 indices_r_loop: do
1310 if(i.ge.right_num_) exit indices_r_loop
1311 i = i + 1
1312 if(any(indices_r(:i-1).eq.indices_r(i)))then
1313 indices_r(i:right_num_-num_redos-1) = &
1314 indices_r(i+1:right_num_-num_redos)
1315 call random_number(rtmp1)
1316 indices_r(right_num_) = floor(rtmp1*size(data,dim)) + 1
1317 i = i - 1
1318 end if
1319 end do indices_r_loop
1320
1321
1322 ! Generate right split
1323 !---------------------------------------------------------------------------
1324 do i=1,5
1325 if(i.eq.dim)then
1326 idx(i)%loc = indices_r
1327 else
1328 idx(i)%loc = (/ ( j, j=1,size(data,i) ) /)
1329 end if
1330 end do
1331 right = data_copy(idx(1)%loc,idx(2)%loc,idx(3)%loc,idx(4)%loc,idx(5)%loc)
1332
1333
1334 ! Get list of indices for left split
1335 !---------------------------------------------------------------------------
1336 indices_l_loop: do i=1,size(data,dim)
1337 if(any(indices_r.eq.i)) cycle indices_l_loop
1338 if(allocated(indices_l)) then
1339 indices_l = [indices_l(:), i]
1340 else
1341 indices_l = [i]
1342 end if
1343 end do indices_l_loop
1344
1345
1346 ! Generate left split
1347 !---------------------------------------------------------------------------
1348 idx(dim)%loc = indices_l
1349 left = data_copy(idx(1)%loc,idx(2)%loc,idx(3)%loc,idx(4)%loc,idx(5)%loc)
1350
1351 end subroutine split_5Drdata
1352 !-------------------------------------------------------------------------------
1353 subroutine split_2Drdata_1Drlist( &
1354 data, label, left_data, right_data, &
1355 left_label, right_label, dim, &
1356 left_size, right_size, &
1357 shuffle, seed, split_list &
1358 )
1359 !! Split a 2D array along one dimension
1360 implicit none
1361
1362 ! Arguments
1363 real(real32), dimension(:,:), intent(in) :: data
1364 !! 2D array to be split
1365 real(real32), dimension(:), intent(in) :: label
1366 !! 1D array to be split
1367 real(real32), allocatable, dimension(:,:), intent(out) :: &
1368 left_data, right_data
1369 !! 2D arrays to store the left and right splits
1370 real(real32), allocatable, dimension(:), intent(out) :: &
1371 left_label, right_label
1372 !! 1D arrays to store the left and right splits
1373 integer, intent(in) :: dim
1374 !! Dimension along which to split
1375 real(real32), optional, intent(in) :: left_size, right_size
1376 !! Size of the left and right splits
1377 logical, optional, intent(in) :: shuffle
1378 !! Shuffle the data before splitting
1379 integer, optional, intent(in) :: seed
1380 !! Random seed
1381 integer, optional, dimension(size(data,dim)), intent(out) :: split_list
1382 !! Index array
1383
1384 ! Local variables
1385 integer :: seed_, left_num_, right_num_
1386 !! Random seed, number of elements in left and right splits
1387 logical :: shuffle_
1388 !! Shuffle flag
1389 integer :: i, j
1390 !! Loop indices
1391 integer :: num_redos
1392 !! Number of redos
1393 real(real32) :: rtmp1
1394 !! Temporary real
1395 integer, allocatable, dimension(:) :: indices_l, indices_r
1396 !! Index arrays
1397 real(real32), allocatable, dimension(:) :: tlist
1398 !! Temporary list
1399 real(real32), allocatable, dimension(:) :: label_copy
1400 !! Copy of the input label
1401 real(real32), allocatable, dimension(:,:) :: data_copy
1402 !! Copy of the input data
1403
1404 type :: idx_type
1405 !! Type for index array
1406 integer, allocatable, dimension(:) :: loc
1407 !! Index array
1408 end type idx_type
1409 type(idx_type), dimension(5) :: idx
1410 !! Index array
1411
1412
1413 ! Determine number of elements for left and right split
1414 !---------------------------------------------------------------------------
1415 if(.not.present(left_size).and..not.present(right_size))then
1416 call stop_program("neither left_size nor right_size provided to split. &
1417 &Expected at least one." &
1418 )
1419 return
1420 elseif(present(left_size).and..not.present(right_size))then
1421 left_num_ = nint(left_size*size(data,dim))
1422 right_num_ = size(data,dim) - left_num_
1423 elseif(.not.present(left_size).and.present(right_size))then
1424 right_num_ = nint(right_size*size(data,dim))
1425 left_num_ = size(data,dim) - right_num_
1426 else
1427 left_num_ = nint(left_size*size(data,dim))
1428 right_num_ = nint(right_size*size(data,dim))
1429 if(left_num_ + right_num_ .ne. size(data,dim)) &
1430 right_num_ = size(data,dim) - left_num_
1431 end if
1432
1433 ! Initialies optional arguments
1434 !---------------------------------------------------------------------------
1435 if(present(shuffle))then
1436 shuffle_ = shuffle
1437 else
1438 shuffle_ = .false.
1439 end if
1440
1441 if(present(seed))then
1442 seed_ = seed
1443 else
1444 call system_clock(count=seed_)
1445 end if
1446
1447
1448 ! Copy input data
1449 !---------------------------------------------------------------------------
1450 data_copy = data
1451 label_copy = label
1452 if(shuffle_) call shuffle_2Drdata_1Drlist(data_copy,label_copy,dim,seed_)
1453
1454
1455 ! Get list of indices for right split
1456 !---------------------------------------------------------------------------
1457 num_redos = 0
1458 allocate(tlist(right_num_))
1459 call random_number(tlist)
1460 indices_r = floor(tlist*size(data,dim)) + 1
1461 i = 1
1462 indices_r_loop: do
1463 if(i.ge.right_num_) exit indices_r_loop
1464 i = i + 1
1465 if(any(indices_r(:i-1).eq.indices_r(i)))then
1466 indices_r(i:right_num_-num_redos-1) = &
1467 indices_r(i+1:right_num_-num_redos)
1468 call random_number(rtmp1)
1469 indices_r(right_num_) = floor(rtmp1*size(data,dim)) + 1
1470 i = i - 1
1471 end if
1472 end do indices_r_loop
1473
1474
1475 ! Generate right split
1476 !---------------------------------------------------------------------------
1477 do i=1,2
1478 if(i.eq.dim)then
1479 idx(i)%loc = indices_r
1480 else
1481 idx(i)%loc = (/ ( j, j=1,size(data,i) ) /)
1482 end if
1483 end do
1484 right_data = data_copy(idx(1)%loc,idx(2)%loc)
1485 right_label = label_copy(indices_r)
1486
1487
1488 ! Get list of indices for left split
1489 !---------------------------------------------------------------------------
1490 if(present(split_list)) split_list = 2
1491 indices_l_loop: do i=1,size(data,dim)
1492 if(any(indices_r.eq.i)) cycle indices_l_loop
1493 if(allocated(indices_l)) then
1494 indices_l = [indices_l(:), i]
1495 else
1496 indices_l = [i]
1497 end if
1498 if(present(split_list)) split_list(i) = 1
1499 end do indices_l_loop
1500
1501
1502 ! Generate left split
1503 !---------------------------------------------------------------------------
1504 idx(dim)%loc = indices_l
1505 left_data = data_copy(idx(1)%loc,idx(2)%loc)
1506 left_label = label_copy(indices_l)
1507
1508 end subroutine split_2Drdata_1Drlist
1509 !-------------------------------------------------------------------------------
1510 subroutine split_3Didata_1Dilist( &
1511 data, label, left_data, right_data, &
1512 left_label, right_label, dim, &
1513 left_size, right_size, &
1514 shuffle, seed, split_list &
1515 )
1516 implicit none
1517
1518 ! Arguments
1519 integer, dimension(:,:,:), intent(in) :: data
1520 !! 3D array to be split
1521 integer, dimension(:), intent(in) :: label
1522 !! 1D array to be split
1523 integer, allocatable, dimension(:,:,:), intent(out) :: left_data, right_data
1524 !! 3D arrays to store the left and right splits
1525 integer, allocatable, dimension(:), intent(out) :: left_label, right_label
1526 !! 1D arrays to store the left and right splits
1527 integer, intent(in) :: dim
1528 !! Dimension along which to split
1529 real(real32), optional, intent(in) :: left_size, right_size
1530 !! Size of the left and right splits
1531 logical, optional, intent(in) :: shuffle
1532 !! Shuffle the data before splitting
1533 integer, optional, intent(in) :: seed
1534 !! Random seed
1535 integer, optional, dimension(size(data,dim)), intent(out) :: split_list
1536 !! Index array
1537
1538 ! Local variables
1539 integer :: seed_, left_num_, right_num_
1540 !! Random seed, number of elements in left and right splits
1541 logical :: shuffle_
1542 !! Shuffle flag
1543 integer :: i, j
1544 !! Loop indices
1545 integer :: num_redos
1546 !! Number of redos
1547 real(real32) :: rtmp1
1548 !! Temporary real
1549 integer, allocatable, dimension(:) :: indices_l, indices_r
1550 !! Index arrays
1551 real(real32), allocatable, dimension(:) :: tlist
1552 !! Temporary list
1553 integer, allocatable, dimension(:) :: label_copy
1554 !! Copy of the input label
1555 integer, allocatable, dimension(:,:,:) :: data_copy
1556 !! Copy of the input data
1557
1558 type :: idx_type
1559 !! Type for index array
1560 integer, allocatable, dimension(:) :: loc
1561 !! Index array
1562 end type idx_type
1563 type(idx_type), dimension(3) :: idx
1564 !! Index array
1565
1566
1567 ! Determine number of elements for left and right split
1568 !---------------------------------------------------------------------------
1569 if(.not.present(left_size).and..not.present(right_size))then
1570 call stop_program("neither left_size nor right_size provided to split. &
1571 &Expected at least one." &
1572 )
1573 return
1574 elseif(present(left_size).and..not.present(right_size))then
1575 left_num_ = nint(left_size*size(data,dim))
1576 right_num_ = size(data,dim) - left_num_
1577 elseif(.not.present(left_size).and.present(right_size))then
1578 right_num_ = nint(right_size*size(data,dim))
1579 left_num_ = size(data,dim) - right_num_
1580 else
1581 left_num_ = nint(left_size*size(data,dim))
1582 right_num_ = nint(right_size*size(data,dim))
1583 if(left_num_ + right_num_ .ne. size(data,dim)) &
1584 right_num_ = size(data,dim) - left_num_
1585 end if
1586
1587 ! Initialies optional arguments
1588 !---------------------------------------------------------------------------
1589 if(present(shuffle))then
1590 shuffle_ = shuffle
1591 else
1592 shuffle_ = .false.
1593 end if
1594
1595 if(present(seed))then
1596 seed_ = seed
1597 else
1598 call system_clock(count=seed_)
1599 end if
1600
1601
1602 ! Copy input data
1603 !---------------------------------------------------------------------------
1604 data_copy = data
1605 label_copy = label
1606 if(shuffle_) call shuffle_3Didata_1Dilist(data_copy,label_copy,dim,seed_)
1607
1608
1609 ! Get list of indices for right split
1610 !---------------------------------------------------------------------------
1611 num_redos = 0
1612 allocate(tlist(right_num_))
1613 call random_number(tlist)
1614 indices_r = floor(tlist*size(data,dim)) + 1
1615 i = 1
1616 indices_r_loop: do
1617 if(i.ge.right_num_) exit indices_r_loop
1618 i = i + 1
1619 if(any(indices_r(:i-1).eq.indices_r(i)))then
1620 indices_r(i:right_num_-num_redos-1) = &
1621 indices_r(i+1:right_num_-num_redos)
1622 call random_number(rtmp1)
1623 indices_r(right_num_) = floor(rtmp1*size(data,dim)) + 1
1624 i = i - 1
1625 end if
1626 end do indices_r_loop
1627
1628
1629 ! Generate right split
1630 !---------------------------------------------------------------------------
1631 do i=1,3
1632 if(i.eq.dim)then
1633 idx(i)%loc = indices_r
1634 else
1635 idx(i)%loc = (/ ( j, j=1,size(data,i) ) /)
1636 end if
1637 end do
1638 right_data = data_copy(&
1639 idx(1)%loc,idx(2)%loc,idx(3)%loc)
1640 right_label = label_copy(indices_r)
1641
1642
1643 ! Get list of indices for left split
1644 !---------------------------------------------------------------------------
1645 if(present(split_list)) split_list = 2
1646 indices_l_loop: do i=1,size(data,dim)
1647 if(any(indices_r.eq.i)) cycle indices_l_loop
1648 if(allocated(indices_l)) then
1649 indices_l = [indices_l(:), i]
1650 else
1651 indices_l = [i]
1652 end if
1653 if(present(split_list)) split_list(i) = 1
1654 end do indices_l_loop
1655
1656
1657 ! Generate left split
1658 !---------------------------------------------------------------------------
1659 idx(dim)%loc = indices_l
1660 left_data = data_copy(&
1661 idx(1)%loc,idx(2)%loc,idx(3)%loc)
1662 left_label = label_copy(indices_l)
1663
1664 end subroutine split_3Didata_1Dilist
1665 !-------------------------------------------------------------------------------
1666 subroutine split_3Didata_1Drlist( &
1667 data, label, left_data, right_data, &
1668 left_label, right_label, dim, &
1669 left_size, right_size, &
1670 shuffle, seed, split_list &
1671 )
1672 !! Split a 3D array along one dimension
1673 implicit none
1674
1675 ! Arguments
1676 integer, dimension(:,:,:), intent(in) :: data
1677 !! 3D array to be split
1678 real(real32), dimension(:), intent(in) :: label
1679 !! 1D array to be split
1680 integer, allocatable, dimension(:,:,:), intent(out) :: left_data, right_data
1681 !! 3D arrays to store the left and right splits
1682 real(real32), allocatable, dimension(:), intent(out) :: &
1683 left_label, right_label
1684 !! 1D arrays to store the left and right splits
1685 integer, intent(in) :: dim
1686 !! Dimension along which to split
1687 real(real32), optional, intent(in) :: left_size, right_size
1688 !! Size of the left and right splits
1689 logical, optional, intent(in) :: shuffle
1690 !! Shuffle the data before splitting
1691 integer, optional, intent(in) :: seed
1692 !! Random seed
1693 integer, optional, dimension(size(data,dim)), intent(out) :: split_list
1694 !! Index array
1695
1696 ! Local variables
1697 integer :: seed_, left_num_, right_num_
1698 !! Random seed, number of elements in left and right splits
1699 logical :: shuffle_
1700 !! Shuffle flag
1701 integer :: i, j
1702 !! Loop indices
1703 integer :: num_redos
1704 !! Number of redos
1705 real(real32) :: rtmp1
1706 !! Temporary real
1707 integer, allocatable, dimension(:) :: indices_l, indices_r
1708 !! Index arrays
1709 real(real32), allocatable, dimension(:) :: tlist
1710 !! Temporary list
1711 real(real32), allocatable, dimension(:) :: label_copy
1712 !! Copy of the input label
1713 integer, allocatable, dimension(:,:,:) :: data_copy
1714 !! Copy of the input data
1715
1716 type :: idx_type
1717 !! Type for index array
1718 integer, allocatable, dimension(:) :: loc
1719 !! Index array
1720 end type idx_type
1721 type(idx_type), dimension(3) :: idx
1722 !! Index array
1723
1724
1725 ! Determine number of elements for left and right split
1726 !---------------------------------------------------------------------------
1727 if(.not.present(left_size).and..not.present(right_size))then
1728 call stop_program("neither left_size nor right_size provided to split. &
1729 &Expected at least one." &
1730 )
1731 return
1732 elseif(present(left_size).and..not.present(right_size))then
1733 left_num_ = nint(left_size*size(data,dim))
1734 right_num_ = size(data,dim) - left_num_
1735 elseif(.not.present(left_size).and.present(right_size))then
1736 right_num_ = nint(right_size*size(data,dim))
1737 left_num_ = size(data,dim) - right_num_
1738 else
1739 left_num_ = nint(left_size*size(data,dim))
1740 right_num_ = nint(right_size*size(data,dim))
1741 if(left_num_ + right_num_ .ne. size(data,dim)) &
1742 right_num_ = size(data,dim) - left_num_
1743 end if
1744
1745 ! Initialies optional arguments
1746 !---------------------------------------------------------------------------
1747 if(present(shuffle))then
1748 shuffle_ = shuffle
1749 else
1750 shuffle_ = .false.
1751 end if
1752
1753 if(present(seed))then
1754 seed_ = seed
1755 else
1756 call system_clock(count=seed_)
1757 end if
1758
1759
1760 ! Copy input data
1761 !---------------------------------------------------------------------------
1762 data_copy = data
1763 label_copy = label
1764 if(shuffle_) call shuffle_3Didata_1Drlist(data_copy,label_copy,dim,seed_)
1765
1766
1767 ! Get list of indices for right split
1768 !---------------------------------------------------------------------------
1769 num_redos = 0
1770 allocate(tlist(right_num_))
1771 call random_number(tlist)
1772 indices_r = floor(tlist*size(data,dim)) + 1
1773 i = 1
1774 indices_r_loop: do
1775 if(i.ge.right_num_) exit indices_r_loop
1776 i = i + 1
1777 if(any(indices_r(:i-1).eq.indices_r(i)))then
1778 indices_r(i:right_num_-num_redos-1) = &
1779 indices_r(i+1:right_num_-num_redos)
1780 call random_number(rtmp1)
1781 indices_r(right_num_) = floor(rtmp1*size(data,dim)) + 1
1782 i = i - 1
1783 end if
1784 end do indices_r_loop
1785
1786
1787 ! Generate right split
1788 !---------------------------------------------------------------------------
1789 do i=1,3
1790 if(i.eq.dim)then
1791 idx(i)%loc = indices_r
1792 else
1793 idx(i)%loc = (/ ( j, j=1,size(data,i) ) /)
1794 end if
1795 end do
1796 right_data = data_copy(&
1797 idx(1)%loc,idx(2)%loc,idx(3)%loc)
1798 right_label = label_copy(indices_r)
1799
1800
1801 ! Get list of indices for left split
1802 !---------------------------------------------------------------------------
1803 if(present(split_list)) split_list = 2
1804 indices_l_loop: do i=1,size(data,dim)
1805 if(any(indices_r.eq.i)) cycle indices_l_loop
1806 if(allocated(indices_l)) then
1807 indices_l = [indices_l(:), i]
1808 else
1809 indices_l = [i]
1810 end if
1811 if(present(split_list)) split_list(i) = 1
1812 end do indices_l_loop
1813
1814
1815 ! Generate left split
1816 !---------------------------------------------------------------------------
1817 idx(dim)%loc = indices_l
1818 left_data = data_copy(&
1819 idx(1)%loc,idx(2)%loc,idx(3)%loc)
1820 left_label = label_copy(indices_l)
1821
1822 end subroutine split_3Didata_1Drlist
1823 !-------------------------------------------------------------------------------
1824 subroutine split_5Drdata_1Drlist( &
1825 data, label, left_data, right_data, &
1826 left_label, right_label, dim, &
1827 left_size, right_size, &
1828 shuffle, seed, split_list &
1829 )
1830 !! Split a 5D array along one dimension
1831 implicit none
1832
1833 ! Arguments
1834 real(real32), dimension(:,:,:,:,:), intent(in) :: data
1835 !! 5D array to be split
1836 real(real32), dimension(:), intent(in) :: label
1837 !! 1D array to be split
1838 real(real32), allocatable, dimension(:,:,:,:,:), intent(out) :: &
1839 left_data, right_data
1840 !! 5D arrays to store the left and right splits
1841 real(real32), allocatable, dimension(:), intent(out) :: &
1842 left_label, right_label
1843 !! 1D arrays to store the left and right splits
1844 integer, intent(in) :: dim
1845 !! Dimension along which to split
1846 real(real32), optional, intent(in) :: left_size, right_size
1847 !! Size of the left and right splits
1848 logical, optional, intent(in) :: shuffle
1849 !! Shuffle the data before splitting
1850 integer, optional, intent(in) :: seed
1851 !! Random seed
1852 integer, optional, dimension(size(data,dim)), intent(out) :: split_list
1853 !! Index array
1854
1855 ! Local variables
1856 integer :: seed_, left_num_, right_num_
1857 !! Random seed, number of elements in left and right splits
1858 logical :: shuffle_
1859 !! Shuffle flag
1860 integer :: i, j
1861 !! Loop indices
1862 integer :: num_redos
1863 !! Number of redos
1864 real(real32) :: rtmp1
1865 !! Temporary real
1866 integer, allocatable, dimension(:) :: indices_l, indices_r
1867 !! Index arrays
1868 real(real32), allocatable, dimension(:) :: tlist
1869 !! Temporary list
1870 real(real32), allocatable, dimension(:) :: label_copy
1871 !! Copy of the input label
1872 real(real32), allocatable, dimension(:,:,:,:,:) :: data_copy
1873 !! Copy of the input data
1874
1875 type :: idx_type
1876 !! Type for index array
1877 integer, allocatable, dimension(:) :: loc
1878 !! Index array
1879 end type idx_type
1880 type(idx_type), dimension(5) :: idx
1881 !! Index array
1882
1883
1884 ! Determine number of elements for left and right split
1885 !---------------------------------------------------------------------------
1886 if(.not.present(left_size).and..not.present(right_size))then
1887 call stop_program("neither left_size nor right_size provided to split. &
1888 &Expected at least one." &
1889 )
1890 return
1891 elseif(present(left_size).and..not.present(right_size))then
1892 left_num_ = nint(left_size*size(data,dim))
1893 right_num_ = size(data,dim) - left_num_
1894 elseif(.not.present(left_size).and.present(right_size))then
1895 right_num_ = nint(right_size*size(data,dim))
1896 left_num_ = size(data,dim) - right_num_
1897 else
1898 left_num_ = nint(left_size*size(data,dim))
1899 right_num_ = nint(right_size*size(data,dim))
1900 if(left_num_ + right_num_ .ne. size(data,dim)) &
1901 right_num_ = size(data,dim) - left_num_
1902 end if
1903
1904
1905 ! Initialies optional arguments
1906 !---------------------------------------------------------------------------
1907 if(present(shuffle))then
1908 shuffle_ = shuffle
1909 else
1910 shuffle_ = .false.
1911 end if
1912
1913 if(present(seed))then
1914 seed_ = seed
1915 else
1916 call system_clock(count=seed_)
1917 end if
1918
1919
1920 ! Copy input data
1921 !---------------------------------------------------------------------------
1922 data_copy = data
1923 label_copy = label
1924 if(shuffle_) call shuffle_5Drdata_1Drlist(data_copy,label_copy,dim,seed_)
1925
1926
1927 ! Get list of indices for right split
1928 !---------------------------------------------------------------------------
1929 num_redos = 0
1930 allocate(tlist(right_num_))
1931 call random_number(tlist)
1932 indices_r = floor(tlist*size(data,dim)) + 1
1933 i = 1
1934 indices_r_loop: do
1935 if(i.ge.right_num_) exit indices_r_loop
1936 i = i + 1
1937 if(any(indices_r(:i-1).eq.indices_r(i)))then
1938 indices_r(i:right_num_-num_redos-1) = &
1939 indices_r(i+1:right_num_-num_redos)
1940 call random_number(rtmp1)
1941 indices_r(right_num_) = floor(rtmp1*size(data,dim)) + 1
1942 i = i - 1
1943 end if
1944 end do indices_r_loop
1945
1946
1947 ! Generate right split
1948 !---------------------------------------------------------------------------
1949 do i=1,5
1950 if(i.eq.dim)then
1951 idx(i)%loc = indices_r
1952 else
1953 idx(i)%loc = (/ ( j, j=1,size(data,i) ) /)
1954 end if
1955 end do
1956 right_data = data_copy(&
1957 idx(1)%loc,idx(2)%loc,idx(3)%loc,idx(4)%loc,idx(5)%loc)
1958 right_label = label_copy(indices_r)
1959
1960
1961 ! Get list of indices for left split
1962 !---------------------------------------------------------------------------
1963 if(present(split_list)) split_list = 2
1964 indices_l_loop: do i=1,size(data,dim)
1965 if(any(indices_r.eq.i)) cycle indices_l_loop
1966 if(allocated(indices_l)) then
1967 indices_l = [indices_l(:), i]
1968 else
1969 indices_l = [i]
1970 end if
1971 if(present(split_list)) split_list(i) = 1
1972 end do indices_l_loop
1973
1974
1975 ! Generate left split
1976 !---------------------------------------------------------------------------
1977 idx(dim)%loc = indices_l
1978 left_data = data_copy(&
1979 idx(1)%loc,idx(2)%loc,idx(3)%loc,idx(4)%loc,idx(5)%loc)
1980 left_label = label_copy(indices_l)
1981
1982 end subroutine split_5Drdata_1Drlist
1983 !###############################################################################
1984
1985
1986 !##############################################################################!
1987 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
1988 !##############################################################################!
1989
1990
1991
1992 !###############################################################################
1993 pure function get_padding_half(width) result(output)
1994 !! Function to return half the padding width
1995 implicit none
1996
1997 ! Arguments
1998 integer, intent(in) :: width
1999 !! Width of kernel/filter
2000 integer :: output
2001 !! Half the padding width
2002
2003 output = ( width - (1 - mod(width,2)) - 1 ) / 2
2004 end function get_padding_half
2005 !###############################################################################
2006
2007
2008 !###############################################################################
2009 subroutine set_padding(pad, kernel_size, padding_method, verbose)
2010 !! Set padding for convolutional layers
2011 use coreutils, only: to_lower
2012 implicit none
2013
2014 ! Arguments
2015 integer, intent(out) :: pad
2016 !! Padding width
2017 integer, intent(in) :: kernel_size
2018 !! Width of kernel/filter
2019 character(*), intent(inout) :: padding_method
2020 !! Padding method
2021 integer, optional, intent(in) :: verbose
2022 !! Verbosity level
2023
2024 ! Local variables
2025 integer :: t_verbose = 0
2026 !! Temporary verbosity level
2027 character(256) :: err_msg
2028 !! Error message
2029
2030
2031 !---------------------------------------------------------------------------
2032 ! initialise optional arguments
2033 !---------------------------------------------------------------------------
2034 if(present(verbose)) t_verbose = verbose
2035
2036
2037 !---------------------------------------------------------------------------
2038 ! Padding method options
2039 !---------------------------------------------------------------------------
2040 ! none = alt. name for 'valid'
2041 ! zero = alt. name for 'same'
2042 ! symmetric = alt.name for 'replication'
2043 ! valid = no padding
2044 ! same = maintain spatial dimensions
2045 ! ... (i.e. padding added = (kernel_size - 1)/2)
2046 ! ... defaults to zeros in the padding
2047 ! full = enough padding for filter to slide over every possible position
2048 ! ... (i.e. padding added = (kernel_size - 1)
2049 ! circular = maintain spatial dimensions
2050 ! ... wraps data around for padding (periodic)
2051 ! reflection = maintains spatial dimensions
2052 ! ... reflect data (about boundary index)
2053 ! replication = maintains spatial dimensions
2054 ! ... reflect data (boundary included)
2055 100 select case(to_lower(trim(padding_method)))
2056 case("none")
2057 padding_method = "valid"
2058 goto 100
2059 case("zero")
2060 padding_method = "same"
2061 goto 100
2062 case("half")
2063 padding_method = "same"
2064 goto 100
2065 case("symmetric")
2066 padding_method = "replication"
2067 goto 100
2068 case("valid", "vali")
2069 if(t_verbose.gt.0) write(*,*) "Padding type: 'valid' (no padding)"
2070 pad = 0
2071 return
2072 case("same")
2073 if(t_verbose.gt.0) write(*,*) "Padding type: 'same' (pad with zeros)"
2074 case("circular")
2075 if(t_verbose.gt.0) write(*,*) "Padding type: 'same' (circular padding)"
2076 case("full")
2077 if(t_verbose.gt.0) write(*,*) &
2078 "Padding type: 'full' (all possible positions)"
2079 pad = kernel_size - 1
2080 return
2081 case("reflection")
2082 if(t_verbose.gt.0) write(*,*) &
2083 "Padding type: 'reflection' (reflect on boundary)"
2084 case("replication")
2085 if(t_verbose.gt.0) write(*,*) &
2086 "Padding type: 'replication' (reflect after boundary)"
2087 case default
2088 write(err_msg,'("padding type ''",A,"'' not known")') padding_method
2089 call stop_program(err_msg)
2090 return
2091 end select
2092
2093 pad = get_padding_half(kernel_size)
2094
2095 end subroutine set_padding
2096 !###############################################################################
2097
2098
2099 !###############################################################################
2100 subroutine pad_data( &
2101 data, data_padded, &
2102 kernel_size, padding_method, &
2103 sample_dim, channel_dim, constant &
2104 )
2105 !! Pad data for convolutional layers
2106 implicit none
2107
2108 ! Arguments
2109 real(real32), dimension(..), intent(in) :: data
2110 !! Data to be padded
2111 real(real32), allocatable, dimension(..), intent(out) :: data_padded
2112 !! Padded data
2113 integer, dimension(..), intent(in) :: kernel_size
2114 !! Width of kernel/filter
2115 character(*), intent(inout) :: padding_method
2116 !! Padding method
2117 real(real32), optional, intent(in) :: constant
2118 !! Constant value for padding
2119 integer, optional, intent(in) :: sample_dim, channel_dim
2120 !! Dimensions along which to pad
2121
2122 ! Local variables
2123 integer :: i, j, idim
2124 !! Loop indices
2125 integer :: num_samples, num_channels, ndim, ndata_dim
2126 !! Number of samples, channels, dimensions
2127 integer :: sample_dim_ = 0, channel_dim_ = 0
2128 !! Sample and channel dimensions
2129 real(real32) :: constant_ = 0._real32
2130 !! Constant value for padding
2131 integer, dimension(2) :: bound_store
2132 !! Store boundary indices
2133 integer, allocatable, dimension(:) :: padding
2134 !! Padding width
2135 integer, allocatable, dimension(:,:) :: trgt_bound, dest_bound
2136 !! Target and destination boundaries
2137 integer, allocatable, dimension(:,:) :: tmp_trgt_bound, tmp_dest_bound
2138 !! Temporary target and destination boundaries
2139
2140 character(256) :: err_msg
2141 !! Error message
2142
2143
2144 !---------------------------------------------------------------------------
2145 ! Initialise optional arguments
2146 !---------------------------------------------------------------------------
2147 if(present(constant)) constant_ = constant
2148 if(present(sample_dim)) sample_dim_ = sample_dim
2149 if(present(channel_dim)) channel_dim_ = channel_dim
2150
2151 ndim = rank(data)
2152 #if defined(GFORTRAN)
2153 if(ndim.ne.rank(data_padded)) then
2154 call stop_program("data and data_padded are not the same rank")
2155 return
2156 end if
2157 #else
2158 select rank(data_padded)
2159 rank(1)
2160 if(ndim.ne.1)then
2161 call stop_program("data and data_padded are not the same rank")
2162 return
2163 end if
2164 rank(2)
2165 if(ndim.ne.2)then
2166 call stop_program("data and data_padded are not the same rank")
2167 return
2168 end if
2169 rank(3)
2170 if(ndim.ne.3)then
2171 call stop_program("data and data_padded are not the same rank")
2172 return
2173 end if
2174 rank(4)
2175 if(ndim.ne.4)then
2176 call stop_program("data and data_padded are not the same rank")
2177 return
2178 end if
2179 rank(5)
2180 if(ndim.ne.5)then
2181 call stop_program("data and data_padded are not the same rank")
2182 return
2183 end if
2184 end select
2185 #endif
2186 ndata_dim = ndim
2187 if(sample_dim_.gt.0) ndata_dim = ndata_dim - 1
2188 if(channel_dim_.gt.0) ndata_dim = ndata_dim - 1
2189
2190 select rank(data)
2191 rank(1)
2192 if(sample_dim_.gt.0) num_samples = size(data,sample_dim_)
2193 if(channel_dim_.gt.0) num_channels = size(data,channel_dim_)
2194 rank(2)
2195 if(sample_dim_.gt.0) num_samples = size(data,sample_dim_)
2196 if(channel_dim_.gt.0) num_channels = size(data,channel_dim_)
2197 rank(3)
2198 if(sample_dim_.gt.0) num_samples = size(data,sample_dim_)
2199 if(channel_dim_.gt.0) num_channels = size(data,channel_dim_)
2200 rank(4)
2201 if(sample_dim_.gt.0) num_samples = size(data,sample_dim_)
2202 if(channel_dim_.gt.0) num_channels = size(data,channel_dim_)
2203 rank(5)
2204 if(sample_dim_.gt.0) num_samples = size(data,sample_dim_)
2205 if(channel_dim_.gt.0) num_channels = size(data,channel_dim_)
2206 rank default
2207 call stop_program("cannot handle data with this rank")
2208 return
2209 end select
2210
2211
2212 !---------------------------------------------------------------------------
2213 ! Handle padding type name
2214 !---------------------------------------------------------------------------
2215 ! none = alt. name for 'valid'
2216 ! zero = alt. name for 'same'
2217 ! symmetric = alt.name for 'replication'
2218 ! valid = no padding
2219 ! same = maintain spatial dimensions
2220 ! ... (i.e. padding added = (kernel_size - 1)/2)
2221 ! ... defaults to zeros in the padding
2222 ! full = enough padding for filter to slide over every possible position
2223 ! ... (i.e. padding added = (kernel_size - 1)
2224 ! circular = maintain spatial dimensions
2225 ! ... wraps data around for padding (periodic)
2226 ! reflection = maintains spatial dimensions
2227 ! ... reflect data (about boundary index)
2228 ! replication = maintains spatial dimensions
2229 ! ... reflect data (boundary included)
2230 select rank(kernel_size)
2231 rank(0)
2232 allocate(padding(ndata_dim))
2233 do i=1,ndata_dim
2234 call set_padding(padding(i), kernel_size, padding_method, verbose=0)
2235 end do
2236 rank(1)
2237 if(size(kernel_size).eq.1.and.ndata_dim.gt.1)then
2238 allocate(padding(ndata_dim))
2239 do i=1,ndata_dim
2240 call set_padding( &
2241 padding(i), &
2242 kernel_size(1), &
2243 padding_method, &
2244 verbose = 0 &
2245 )
2246 end do
2247 else
2248 if(sample_dim_.eq.0.and.channel_dim_.eq.0.and.&
2249 size(kernel_size).ne.ndim)then
2250 write(err_msg,'("&
2251 &kernel_size length not equal to rank of data",A,"&
2252 &kernel dimension: ",I0,A,"&
2253 &data rank: ",I0)' &
2254 ) &
2255 achar(13) // achar(10), size(kernel_size), &
2256 achar(13) // achar(10), ndim
2257 call stop_program(err_msg)
2258 return
2259 elseif(sample_dim_.gt.0.and.channel_dim_.gt.0.and.&
2260 size(kernel_size).ne.ndim-2)then
2261 write(err_msg,'("&
2262 &kernel_size length not equal to rank of data-2",A,"&
2263 &kernel dimension: ",I0,A,"&
2264 &data rank: ",I0)' &
2265 ) &
2266 achar(13) // achar(10), size(kernel_size), &
2267 achar(13) // achar(10), ndim-2
2268 call stop_program(err_msg)
2269 return
2270 elseif(xor(sample_dim_.gt.0,channel_dim_.gt.0).and.&
2271 size(kernel_size).ne.ndim-1)then
2272 write(err_msg,'("&
2273 &kernel_size length not equal to rank of data-1",A,"&
2274 &kernel dimension: ",I0,A,"&
2275 &data rank: ",I0)' &
2276 ) &
2277 achar(13) // achar(10), size(kernel_size), &
2278 achar(13) // achar(10), ndim-1
2279 call stop_program(err_msg)
2280 return
2281 else
2282 allocate(padding(size(kernel_size)))
2283 end if
2284 do i=1,size(kernel_size)
2285 call set_padding( &
2286 padding(i), kernel_size(i), padding_method, verbose=0 &
2287 )
2288 end do
2289 end if
2290 end select
2291
2292
2293 !---------------------------------------------------------------------------
2294 ! Allocate data set
2295 ! ... if appropriate, add padding
2296 !---------------------------------------------------------------------------
2297 select case(padding_method)
2298 case("same")
2299 case("full")
2300 case("zero")
2301 case default
2302 if(abs(constant_).gt.1.E-8)then
2303 write(*,*) "WARNING: constant is ignored for selected padding method"
2304 end if
2305 end select
2306
2307
2308 allocate(dest_bound(2,ndim))
2309 allocate(trgt_bound(2,ndim))
2310 i = 0
2311 do idim=1,ndim
2312 trgt_bound(:,idim) = [ lbound(data,dim=idim), ubound(data,dim=idim) ]
2313 dest_bound(:,idim) = trgt_bound(:,idim)
2314 if(idim.eq.sample_dim_.or.idim.eq.channel_dim_) cycle
2315 i = i + 1
2316 dest_bound(:,idim) = dest_bound(:,idim) + [ -padding(i), padding(i) ]
2317 end do
2318
2319 select rank(data_padded)
2320 rank(1)
2321 allocate(data_padded(&
2322 dest_bound(1,1):dest_bound(2,1)), source = constant_)
2323
2324 ! Copy input data
2325 !------------------------------------------------------------------------
2326 select rank(data)
2327 rank(1)
2328 data_padded( &
2329 trgt_bound(1,1):trgt_bound(2,1) &
2330 ) = data( &
2331 trgt_bound(1,1):trgt_bound(2,1) &
2332 )
2333 end select
2334 rank(2)
2335 allocate(data_padded(&
2336 dest_bound(1,1):dest_bound(2,1), &
2337 dest_bound(1,2):dest_bound(2,2)), source = constant_)
2338
2339 ! Copy input data
2340 !------------------------------------------------------------------------
2341 select rank(data)
2342 rank(2)
2343 data_padded( &
2344 trgt_bound(1,1) : trgt_bound(2,1), &
2345 trgt_bound(1,2) : trgt_bound(2,2) &
2346 ) = data( &
2347 trgt_bound(1,1) : trgt_bound(2,1), &
2348 trgt_bound(1,2) : trgt_bound(2,2) &
2349 )
2350 end select
2351 rank(3)
2352 allocate( &
2353 data_padded(&
2354 dest_bound(1,1):dest_bound(2,1),&
2355 dest_bound(1,2):dest_bound(2,2),&
2356 dest_bound(1,3):dest_bound(2,3) &
2357 ), source = constant_ &
2358 )
2359
2360 ! Copy input data
2361 !------------------------------------------------------------------------
2362 select rank(data)
2363 rank(3)
2364 data_padded( &
2365 trgt_bound(1,1):trgt_bound(2,1), &
2366 trgt_bound(1,2):trgt_bound(2,2), &
2367 trgt_bound(1,3):trgt_bound(2,3) &
2368 ) = data( &
2369 trgt_bound(1,1):trgt_bound(2,1), &
2370 trgt_bound(1,2):trgt_bound(2,2), &
2371 trgt_bound(1,3):trgt_bound(2,3) &
2372 )
2373 end select
2374 rank(4)
2375 allocate( &
2376 data_padded( &
2377 dest_bound(1,1):dest_bound(2,1), &
2378 dest_bound(1,2):dest_bound(2,2), &
2379 dest_bound(1,3):dest_bound(2,3), &
2380 dest_bound(1,4):dest_bound(2,4) &
2381 ), source = constant_ &
2382 )
2383
2384 ! Copy input data
2385 !------------------------------------------------------------------------
2386 select rank(data)
2387 rank(4)
2388 data_padded( &
2389 trgt_bound(1,1):trgt_bound(2,1), &
2390 trgt_bound(1,2):trgt_bound(2,2), &
2391 trgt_bound(1,3):trgt_bound(2,3), &
2392 trgt_bound(1,4):trgt_bound(2,4) &
2393 ) = data( &
2394 trgt_bound(1,1):trgt_bound(2,1), &
2395 trgt_bound(1,2):trgt_bound(2,2), &
2396 trgt_bound(1,3):trgt_bound(2,3), &
2397 trgt_bound(1,4):trgt_bound(2,4) &
2398 )
2399 end select
2400 rank(5)
2401 allocate( &
2402 data_padded(&
2403 dest_bound(1,1):dest_bound(2,1), &
2404 dest_bound(1,2):dest_bound(2,2), &
2405 dest_bound(1,3):dest_bound(2,3), &
2406 dest_bound(1,4):dest_bound(2,4), &
2407 dest_bound(1,5):dest_bound(2,5) &
2408 ), source = constant_ &
2409 )
2410
2411 ! Copy input data
2412 !------------------------------------------------------------------------
2413 select rank(data)
2414 rank(5)
2415 data_padded( &
2416 trgt_bound(1,1):trgt_bound(2,1), &
2417 trgt_bound(1,2):trgt_bound(2,2), &
2418 trgt_bound(1,3):trgt_bound(2,3), &
2419 trgt_bound(1,4):trgt_bound(2,4), &
2420 trgt_bound(1,5):trgt_bound(2,5) &
2421 ) = data( &
2422 trgt_bound(1,1):trgt_bound(2,1), &
2423 trgt_bound(1,2):trgt_bound(2,2), &
2424 trgt_bound(1,3):trgt_bound(2,3), &
2425 trgt_bound(1,4):trgt_bound(2,4), &
2426 trgt_bound(1,5):trgt_bound(2,5) &
2427 )
2428 end select
2429 end select
2430
2431
2432 !---------------------------------------------------------------------------
2433 ! Return if constant -- or no -- padding
2434 !---------------------------------------------------------------------------
2435 select case(padding_method)
2436 case ("same")
2437 return
2438 case("full")
2439 return
2440 case("zero")
2441 return
2442 case("valid", "vali")
2443 return
2444 end select
2445
2446
2447 !---------------------------------------------------------------------------
2448 ! Insert padding
2449 !---------------------------------------------------------------------------
2450 i = 0
2451 do idim=1,ndim
2452 if(idim.eq.sample_dim_.or.idim.eq.channel_dim_) cycle
2453 i = i + 1
2454 tmp_dest_bound = dest_bound
2455 tmp_trgt_bound = dest_bound
2456 tmp_dest_bound(:,idim) = [ dest_bound(1,idim), trgt_bound(1,idim) - 1 ]
2457 select case(padding_method)
2458 case ("circular")
2459 tmp_trgt_bound(:,idim) = &
2460 [ trgt_bound(2,idim) - padding(i) + 1, trgt_bound(2,idim) ]
2461 case("reflection")
2462 tmp_trgt_bound(:,idim) = &
2463 [ trgt_bound(1,idim) + 1, trgt_bound(1,idim) + padding(i) ]
2464 case("replication")
2465 tmp_trgt_bound(:,idim) = &
2466 [ trgt_bound(1,idim), trgt_bound(1,idim) + padding(i) - 1 ]
2467 end select
2468 do j = 1, 2
2469 select rank(data_padded)
2470 rank(1)
2471 data_padded( &
2472 tmp_dest_bound(1,1):tmp_dest_bound(2,1) &
2473 ) = data_padded( &
2474 tmp_trgt_bound(1,1):tmp_trgt_bound(2,1) &
2475 )
2476 rank(2)
2477 data_padded( &
2478 tmp_dest_bound(1,1):tmp_dest_bound(2,1), &
2479 tmp_dest_bound(1,2):tmp_dest_bound(2,2) &
2480 ) = data_padded( &
2481 tmp_trgt_bound(1,1):tmp_trgt_bound(2,1), &
2482 tmp_trgt_bound(1,2):tmp_trgt_bound(2,2) &
2483 )
2484 rank(3)
2485 data_padded( &
2486 tmp_dest_bound(1,1):tmp_dest_bound(2,1), &
2487 tmp_dest_bound(1,2):tmp_dest_bound(2,2), &
2488 tmp_dest_bound(1,3):tmp_dest_bound(2,3) &
2489 ) = data_padded( &
2490 tmp_trgt_bound(1,1):tmp_trgt_bound(2,1), &
2491 tmp_trgt_bound(1,2):tmp_trgt_bound(2,2), &
2492 tmp_trgt_bound(1,3):tmp_trgt_bound(2,3) &
2493 )
2494 rank(4)
2495 data_padded( &
2496 tmp_dest_bound(1,1):tmp_dest_bound(2,1), &
2497 tmp_dest_bound(1,2):tmp_dest_bound(2,2), &
2498 tmp_dest_bound(1,3):tmp_dest_bound(2,3), &
2499 tmp_dest_bound(1,4):tmp_dest_bound(2,4) &
2500 ) = data_padded( &
2501 tmp_trgt_bound(1,1):tmp_trgt_bound(2,1), &
2502 tmp_trgt_bound(1,2):tmp_trgt_bound(2,2), &
2503 tmp_trgt_bound(1,3):tmp_trgt_bound(2,3), &
2504 tmp_trgt_bound(1,4):tmp_trgt_bound(2,4) &
2505 )
2506 rank(5)
2507 data_padded( &
2508 tmp_dest_bound(1,1):tmp_dest_bound(2,1), &
2509 tmp_dest_bound(1,2):tmp_dest_bound(2,2), &
2510 tmp_dest_bound(1,3):tmp_dest_bound(2,3), &
2511 tmp_dest_bound(1,4):tmp_dest_bound(2,4), &
2512 tmp_dest_bound(1,5):tmp_dest_bound(2,5) &
2513 ) = data_padded( &
2514 tmp_trgt_bound(1,1):tmp_trgt_bound(2,1), &
2515 tmp_trgt_bound(1,2):tmp_trgt_bound(2,2), &
2516 tmp_trgt_bound(1,3):tmp_trgt_bound(2,3), &
2517 tmp_trgt_bound(1,4):tmp_trgt_bound(2,4), &
2518 tmp_trgt_bound(1,5):tmp_trgt_bound(2,5) &
2519 )
2520 end select
2521
2522 if(j.eq.2) exit
2523 bound_store(:) = tmp_dest_bound(:,idim)
2524 select case(padding_method)
2525 case ("circular")
2526 tmp_dest_bound(:,idim) = tmp_trgt_bound(:,idim) + padding(i)
2527 tmp_trgt_bound(:,idim) = bound_store(:) + padding(i)
2528 case("reflection")
2529 tmp_dest_bound(:,idim) = &
2530 tmp_trgt_bound(:,idim) + size(data,idim) - 1
2531 tmp_trgt_bound(:,idim) = bound_store(:) + size(data,idim) - 1
2532 case("replication")
2533 tmp_dest_bound(:,idim) = tmp_trgt_bound(:,idim) + size(data,idim)
2534 tmp_trgt_bound(:,idim) = bound_store(:) + size(data,idim)
2535 end select
2536 end do
2537 end do
2538
2539 end subroutine pad_data
2540 !###############################################################################
2541
2542
59/82
✓ Branch 0 (8→9) taken 10 times.
✓ Branch 1 (8→16) taken 53 times.
✓ Branch 2 (16→17) taken 20 times.
✓ Branch 3 (16→24) taken 33 times.
✓ Branch 4 (24→25) taken 12 times.
✓ Branch 5 (24→32) taken 21 times.
✓ Branch 6 (32→33) taken 11 times.
✓ Branch 7 (32→40) taken 10 times.
✓ Branch 8 (40→41) taken 10 times.
✗ Branch 9 (40→48) not taken.
✓ Branch 10 (52→53) taken 63 times.
✗ Branch 11 (52→54) not taken.
✓ Branch 12 (53→54) taken 63 times.
✗ Branch 13 (53→55) not taken.
✓ Branch 14 (56→57) taken 10 times.
✓ Branch 15 (56→62) taken 53 times.
✓ Branch 16 (62→63) taken 20 times.
✓ Branch 17 (62→68) taken 33 times.
✓ Branch 18 (68→69) taken 12 times.
✓ Branch 19 (68→74) taken 21 times.
✓ Branch 20 (74→75) taken 11 times.
✓ Branch 21 (74→80) taken 10 times.
✓ Branch 22 (80→81) taken 10 times.
✗ Branch 23 (80→86) not taken.
✓ Branch 24 (87→88) taken 3 times.
✓ Branch 25 (87→89) taken 60 times.
✓ Branch 26 (88→89) taken 3 times.
✗ Branch 27 (88→90) not taken.
✓ Branch 28 (91→92) taken 60 times.
✓ Branch 29 (91→119) taken 3 times.
✓ Branch 30 (119→120) taken 3 times.
✗ Branch 31 (119→210) not taken.
✓ Branch 32 (355→356) taken 10 times.
✓ Branch 33 (355→460) taken 53 times.
✓ Branch 34 (400→401) taken 10 times.
✗ Branch 35 (400→402) not taken.
✓ Branch 36 (401→402) taken 10 times.
✗ Branch 37 (401→403) not taken.
✓ Branch 38 (404→405) taken 10 times.
✗ Branch 39 (404→459) not taken.
✓ Branch 40 (460→461) taken 20 times.
✓ Branch 41 (460→650) taken 33 times.
✓ Branch 42 (537→538) taken 20 times.
✗ Branch 43 (537→539) not taken.
✓ Branch 44 (538→539) taken 20 times.
✗ Branch 45 (538→540) not taken.
✓ Branch 46 (541→542) taken 20 times.
✗ Branch 47 (541→649) not taken.
✓ Branch 48 (650→651) taken 12 times.
✓ Branch 49 (650→925) taken 21 times.
✓ Branch 50 (759→760) taken 12 times.
✗ Branch 51 (759→761) not taken.
✓ Branch 52 (760→761) taken 12 times.
✗ Branch 53 (760→762) not taken.
✓ Branch 54 (763→764) taken 12 times.
✗ Branch 55 (763→924) not taken.
✓ Branch 56 (925→926) taken 11 times.
✓ Branch 57 (925→1285) taken 10 times.
✓ Branch 58 (1066→1067) taken 11 times.
✗ Branch 59 (1066→1068) not taken.
✓ Branch 60 (1067→1068) taken 11 times.
✗ Branch 61 (1067→1069) not taken.
✓ Branch 62 (1070→1071) taken 11 times.
✗ Branch 63 (1070→1284) not taken.
✓ Branch 64 (1285→1286) taken 10 times.
✗ Branch 65 (1285→1730) not taken.
✓ Branch 66 (1458→1459) taken 10 times.
✗ Branch 67 (1458→1460) not taken.
✓ Branch 68 (1459→1460) taken 10 times.
✗ Branch 69 (1459→1461) not taken.
✓ Branch 70 (1462→1463) taken 10 times.
✗ Branch 71 (1462→1729) not taken.
✓ Branch 72 (1977→1978) taken 8 times.
✓ Branch 73 (1977→2038) taken 64 times.
✓ Branch 74 (2038→2039) taken 16 times.
✓ Branch 75 (2038→2155) taken 48 times.
✓ Branch 76 (2155→2156) taken 8 times.
✓ Branch 77 (2155→2328) taken 40 times.
✓ Branch 78 (2328→2329) taken 16 times.
✓ Branch 79 (2328→2557) taken 24 times.
✓ Branch 80 (2557→2558) taken 24 times.
✗ Branch 81 (2557→2842) not taken.
387 end module athena__misc_ml
2543