Ignore:
Timestamp:
Jul 2, 2025, 3:51:41 PM (8 days ago)
Author:
dcugnet
Message:

Much improved outlayers displaying routine: display compact and readable tables of outlayers.
This version is intended to be used by the isotopes checking routines.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • LMDZ6/trunk/libf/misc/strings_mod.f90

    r5752 r5753  
    15981598
    15991599!==============================================================================================================================
     1600!=== DISPLAY OUTLIERS IN TABLES ===============================================================================================
     1601!==============================================================================================================================
     1602!=== lerr = dispOutliers_1(ll(:), a(:[:]), n(:), err_msg, nam(:), sub, nRowmax, nColMax, unit)
     1603!===  * ll    linearized mask of outliers
     1604!===  * a     linearized fields:
     1605!===    a(:)  all the fields are linearized (all contane
     1606!=== Behaviour depends on ll(:), n(:) and nam(:). We note hereafter nv = SIZE(nam).
     1607!===
     1608!=== 1) if SIZE(ll) == PRODUCT(n) and nv==1 or "nam" is unspecified:           outliers of a single variable are displayed
     1609!===     i[,j[,k]] |       nam       |
     1610!===     ----------+-----------------+
     1611!===     *[,*[,*]] | val(i[,j[,k]])  |
     1612!===        ...    |      ...        |
     1613!===
     1614!===
     1615!=== 2) if SIZE(ll) == PRODUCT(n) and nv>1:                "nv" tables of outliers are displayed, each having its own mask
     1616!===     i[,j] |    var(1)
     1617!===     ------+--------------
     1618!===     *[,*] | val(i[,j],1)
     1619!===      ...  |     ...
     1620!===
     1621!===          ...
     1622!===
     1623!===     i[,j] |    var(nv)
     1624!===     ------+---------------
     1625!===     *[,*] | val(i[,j],nv)
     1626!===      ...  |     ...
     1627!===
     1628!===
     1629!=== 3) if SIZE(ll) = PRODUCT(n(1:SIZE(n)-1):              outliers of "nv" variables are displayed, all with mask "ll(:)"
     1630!===     i[,j] |    var(1)    |    var(2)     |   ...   |    var(nv)       
     1631!===     ------+--------------+---------------+-- ... --+---------------
     1632!===     *[,*] | val(i[,j],1) | val(i[,j],2)  |   ...   | val(i[,j],nv)
     1633!===      ...  |     ...      |     ...       |   ...   |     ...
     1634!===
     1635!===  NOTES:
     1636!===  * in cases 2 and 3, SIZE(nam) MUST be equal to n(SIZE(n)).
     1637!===  * for the sake of readability, narrow tables (compared to the max. width "nColMax") are horizontally stacked.
     1638!===  Here is the result in the case 1:
     1639!===    i[,j[,k]] |       nam       | i[,j[,k]] |       nam       |   ...   | i[,j[,k]] |       nam       
     1640!===    ----------+-----------------+-----------+-----------------+-- ... --+-----------+-----------------
     1641!===    *[,*[,*]] | val(i[,j[,k]])  | *[,*[,*]] | val(i[,j[,k]])  |   ...   | *[,*[,*]] | val(i[,j[,k]])
     1642!===       ...    |      ...        |    ...    |      ...        |   ...   |    ...    |      ...
     1643!===  * conversly, in case 3, too wide tables are displayed as several sub-tables.
     1644!===  * too long tables are truncated to nRowMax lines (excluding titles lines).
     1645!==============================================================================================================================
     1646LOGICAL FUNCTION dispOutliers_1(ll, a, n, err_msg, nam, sub, nRowmax, nColMax, unit) RESULT(lerr)
     1647  IMPLICIT NONE
     1648! Display outliers list in tables
     1649! If "nam" is supplied, it means the last index is for tracers => one table each tracer for rank > 2.
     1650  LOGICAL,                    INTENT(IN)  :: ll(:)                   !--- Linearized mask of outliers
     1651  REAL,                       INTENT(IN)  ::  a(:)                   !--- Linearized array of values
     1652  INTEGER,                    INTENT(IN)  ::  n(:)                   !--- Profile before linearization
     1653  CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: err_msg, nam(:), sub    !--- Error message, variables and calling subroutine names
     1654  INTEGER,          OPTIONAL, INTENT(IN)  :: nRowMax                 !--- Maximum number of lines to display    (default: all)
     1655  INTEGER,          OPTIONAL, INTENT(IN)  :: nColMax                 !--- Maximum number of characters per line (default: 2048)
     1656  INTEGER,          OPTIONAL, INTENT(IN)  :: unit                    !--- Output unit                           (def: lunout)
     1657!------------------------------------------------------------------------------------------------------------------------------
     1658  CHARACTER(LEN=maxlen),      ALLOCATABLE :: t(:), vnm(:), c(:,:)
     1659  LOGICAL,                    ALLOCATABLE :: m(:), ld(:)
     1660  INTEGER,                    ALLOCATABLE :: ki(:), kj(:)
     1661  INTEGER                                 :: rk, ib, ie, itr, nm, unt, nRmx, nCmx, iv, nv, np
     1662  CHARACTER(LEN=maxlen)                   :: mes, subn, fm='(f12.9)', p
     1663  lerr = .FALSE.
     1664
     1665  IF(.NOT.ANY(ll)) RETURN                                            !--- No outliers -> finished
     1666
     1667  mes = 'outliers found'; IF(PRESENT(err_msg)) mes = err_msg         !--- Error message
     1668  vnm = ['a'];            IF(PRESENT(nam))     vnm = nam             !--- Variables names
     1669  subn= 'dispOutliers';   IF(PRESENT(sub))     subn= sub             !--- Calling subroutine name
     1670  nRmx= SIZE(a);          IF(PRESENT(nRowMax)) nRmx=MIN(nRmx,nRowMax)!--- Maximum number of lines to print
     1671  nCmx= 2048;             IF(PRESENT(nColMax)) nCmx=MIN(nCmx,nColMax)!--- Maximum number of characters each line
     1672  unt = lunout;           IF(PRESENT(unit))    unt = unit            !--- Unit to print messages
     1673
     1674  rk = SIZE(n)                                                       !--- Rank of "a" before linearization
     1675  nv = SIZE(vnm)                                                     !--- Number of variables
     1676  np = PRODUCT(n(1:rk-1))                                            !--- Number of points per var (in the multiple vars case)
     1677  lerr = rk>3;                  CALL msg('can display field with rank <=3 only !', subn, lerr, unt); IF(lerr) RETURN
     1678  lerr = n(rk) == 1;            CALL msg('degenerated last dim: n(SIZE(n)) = 1 !', subn, lerr, unt); IF(lerr) RETURN
     1679  lerr = nv/=1 .AND. nv/=n(rk); CALL msg('SIZE(nam) /= 1 and /= last "n" element', subn, lerr, unt); IF(lerr) RETURN
     1680  lerr = SIZE(a) /= PRODUCT(n); CALL msg('profile "n" does not match "a" and "ll', subn, lerr, unt); IF(lerr) RETURN
     1681  lerr = ALL([PRODUCT(n),np] /= SIZE(ll))
     1682  CALL msg('ll" length must be either PROD(n) or PROD(n(1:rk-1))', subn, lerr, unt); IF(lerr) RETURN
     1683
     1684  !============================================================================================================================
     1685  IF(SIZE(ll) == PRODUCT(n)) THEN                                    !=== ll(:) IS A MASK FOR THE WHOLE a(:) VECTOR ===========
     1686  !============================================================================================================================
     1687     p = 's'//REPEAT('r',nv)                                         !--- Display map: one string, "nv" reals
     1688     IF(nv == 1) THEN                                                !=== SINGLE VARIABLE
     1689        CALL buildTitle(n, vnm, t)                                   !--- Build titles list "t" for a single variable
     1690        CALL buildCoord(n, ll, c)                                    !--- Masked ("ll") coordinates vector "c"
     1691        lerr = dispTable(p, t, s=c, r=cat(PACK(a,ll)), rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=1, unit=unt, sub=subn)
     1692     ELSE                                                            !=== MULTIPLE VARIABLES
     1693        DO iv = 1, nv
     1694           CALL buildTitle(n, vnm(iv:iv), t)                         !--- Titles list "t" for the "iv"th variables
     1695           CALL buildCoord(n(1:rk-1), ll, c)                         !--- Masked ("ll") coordinates vector "c"
     1696           ib = 1+(iv-1)*np; ie = ib+np
     1697           lerr = dispTable(p, t, s=c, r=cat(PACK(a(ib:ie),ll(ib:ie))), rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=1, &
     1698                                                                                                    unit=unt, sub=subn)
     1699           CALL msg("can't display outliers table", subn, lerr, unt); IF(lerr) RETURN
     1700        END DO
     1701     END IF
     1702  !============================================================================================================================
     1703  ELSE                                                              !=== ll(:) IS A MASK FOR EACH TRACER STACKED IN a(:) VECTOR
     1704  !============================================================================================================================
     1705     CALL buildTitle(n, vnm, t)                                     !--- Build titles list "t" for all the variable
     1706     CALL duplicate(ll, nv, ld)                                     !--- "ll" concatenated "nv" times
     1707     CALL buildCoord(n(1:rk-1), ll, c)                              !--- Masked ("ll") coordinates vector "c"
     1708     lerr = dispTable(p, t, s=c, r=RESHAPE(PACK(a,ld),[np,nv]), rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=1,unit=unt,sub=subn)
     1709  !============================================================================================================================
     1710  END IF
     1711  !============================================================================================================================
     1712  CALL msg("can't display outliers table", subn, lerr, unt)
     1713
     1714CONTAINS
     1715
     1716SUBROUTINE buildTitle(n, vname, title)                               !=== BUILD TITLES: [COORD. NAME, THE VARIABLE(S) NAME(S)]
     1717  INTEGER,                            INTENT(IN)  ::     n(:)
     1718  CHARACTER(LEN=maxlen),              INTENT(IN)  :: vname(:)
     1719  CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: title(:)
     1720  INTEGER :: rk
     1721  rk = SIZE(n)
     1722  ALLOCATE(title(1+SIZE(vname)))
     1723  title(2:SIZE(vname)+1) = vname
     1724  title(1) = 'i'
     1725  IF(rk >= 2) title(1) = TRIM(title(1))//', j'
     1726  IF(rk >= 3) title(1) = TRIM(title(1))//', k'
     1727END SUBROUTINE buildTitle
     1728
     1729SUBROUTINE buildCoord(n, mask, coord)                                !=== BUILD MASKED COORDINATES OK FOR "s" ARG OF dispTable
     1730  INTEGER,                            INTENT(IN)  ::     n(:)
     1731  LOGICAL,                            INTENT(IN)  ::  mask(:)
     1732  CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: coord(:,:)
     1733  CHARACTER(LEN=maxlen) :: sj, sk
     1734  INTEGER :: i, j, k, m(3), rk, ic
     1735  rk = SIZE(n)
     1736  m(:) = 1;  m(1:rk) = n(:)
     1737  ALLOCATE(coord(1,COUNT(mask)))
     1738  ic = 0
     1739  DO k = 1, m(3); sk = ', '//num2str(k)
     1740     DO j = 1, m(2); sj = ', '//num2str(j)
     1741        DO i = 1, m(1)
     1742           IF(.NOT.mask(i+m(1)*(j+m(2)*k))) CYCLE
     1743           ic = ic+1
     1744           coord(ic,1) = num2str(i)
     1745           IF(rk >= 2) coord(ic,1) = TRIM(coord(ic,1))//TRIM(sj)
     1746           IF(rk >= 3) coord(ic,1) = TRIM(coord(ic,1))//TRIM(sk)
     1747        END DO
     1748     END DO
     1749  END DO
     1750END SUBROUTINE buildCoord
     1751
     1752END FUNCTION dispOutliers_1
     1753!==============================================================================================================================
     1754LOGICAL FUNCTION dispOutliers_2(ll, a, n, err_msg, nam, sub, nRowmax, nColMax, unit) RESULT(lerr)
     1755  IMPLICIT NONE
     1756! Display outliers list in tables
     1757! If "nam" is supplied, it means the last index is for tracers => one table each tracer for rank > 2.
     1758  LOGICAL,                    INTENT(IN)  :: ll(:)                   !--- Linearized mask of outliers
     1759  REAL,                       INTENT(IN)  ::  a(:,:)                 !--- Linearized array of values
     1760  INTEGER,                    INTENT(IN)  ::  n(:)                   !--- Profile before linearization
     1761  CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: err_msg, nam(:), sub    !--- Error message, variables and calling subroutine names
     1762  INTEGER,          OPTIONAL, INTENT(IN)  :: nRowMax                 !--- Maximum number of lines to display    (default: all)
     1763  INTEGER,          OPTIONAL, INTENT(IN)  :: nColMax                 !--- Maximum number of characters per line (default: 2048)
     1764  INTEGER,          OPTIONAL, INTENT(IN)  :: unit                    !--- Output unit                           (def: lunout)
     1765!------------------------------------------------------------------------------------------------------------------------------
     1766  lerr = dispOutliers_1(ll, PACK(a, MASK=.TRUE.), n, err_msg, nam, sub, nRowmax, nColMax, unit)
     1767END FUNCTION dispOutliers_2
     1768!==============================================================================================================================
     1769
     1770
     1771!==============================================================================================================================
    16001772!=== Reduce an algebrical expression (basic operations and parenthesis) to a single number (string format) ====================
    16011773!==============================================================================================================================
Note: See TracChangeset for help on using the changeset viewer.