text:
Computed CD4 percentage as a low-cost method for determining pediatric antiretroviral treatment eligibility
Steven FJ Callens1,
Faustin Kitetele2,
Jean Lusiama2,
Nicole Shabani2,
Samuel Edidi3,
Robert Colebunders4,
Frieda Behets1 &
Annelies Van Rie1
The performance of the WHO recommendations for pediatric antiretroviral treatment (ART) in resource poor settings is insufficiently documented in routine care.
We compared clinical and immunological criteria in 366 children aged 0 to 12 years in Kinshasa and evaluated a simple computation to estimate CD4 percent, based on CD4 count, total white blood cell count and percentage lymphocytes. Kappa (κ) statistic was used to evaluate eligibility criteria and linear regression to determine trends of CD4 percent, count and total lymphocyte count (TLC).
Agreement between clinical and immunological eligibility criteria was poor (κ = 0.26). One third of children clinically eligible for ART were ineligible using immunological criteria; one third of children immunologically eligible were ineligible using clinical criteria. Among children presenting in WHO stage I or II, 54 (32%) were eligible according to immunological criteria. Agreement with CD4 percent was poor for TLC (κ = 0.04), fair for total CD4 count (κ = 0.39) and substantial for CD4 percent computational estimate (κ = 0.71). Among 5 to 12 years old children, total CD4 count was higher in younger age groups (-32 cells/mm3 per year older), CD4 percent was similar across age groups.
Age-specific thresholds for CD4 percent optimally determine pediatric ART eligibility. The use of CD4 percent computational estimate may increase ART access in settings with limited access to CD4 percent assays.
To facilitate the rapid scale-up of pediatric antiretroviral treatment (ART), the World Health Organization (WHO) published revised pediatric ART guidelines for resource poor settings in 2006 [1]. The ART eligibility criteria for infants and children rely on clinical and/or immunological thresholds and aim to identify those children with poor prognosis if ART initiation is delayed.
The WHO clinical staging system has been widely used in resource-limited countries, particularly in the African Region, and has proved pragmatic and useful in facilities at the primary care and referral level [1]. An evaluation of the guidelines in Zambia showed 20-fold higher mortality rates in children with WHO clinical stage IV compared to stages I and II, confirming the association of clinical stage with prognosis [2].
Similarly, WHO immunological thresholds for total CD4+ T lymphocyte count (CD4 count) and CD4 percent (Table 1) are associated with prognosis, and correspond to a 5% annual mortality risk in US and European children aged one year or older [3]. An identical level of immunosuppression in children in resource poor settings may however not have the same prognostic value due to differences in genetic and environmental factors such as opportunistic infections or malnutrition [4, 5]. For example, CD4 percent and CD4 count in healthy Kenyan children was markedly lower compared to children from Europe, USA and West Africa [6]. It is therefore uncertain whether the use of thresholds established through longitudinal studies in the US and Europe can be extrapolated to other regions in the world.
Table 1 Age-specific ART eligibility criteria for children in resource poor settings. Source: World Health Organization: Antiretroviral therapy of HIV infection in infants and children in resource-limited settings: towards universal access. Recommendations for a public health approach, 2006.
We evaluated the impact of the 2006 WHO pediatric ART eligibility criteria on ART initiation decision making in a pediatric HIV care program in Kinshasa, Democratic Republic of Congo (DRC) and propose a lower cost alternative for the expensive CD4 percent assays.
Study setting
The family-centered "Sustainable AntiRetroviral Access (SARA)" Program at Kalembe Lembe pediatric hospital in Kinshasa started in November 2004 and was one of the first to provide free access to pediatric ART in the DRC. The program provides prophylaxis and treatment for opportunistic infections, psychosocial support, nutritional support, insecticide treated bed nets, as well as antiretroviral treatment, according to national guidelines. ART eligibility was defined based on the 2004 and 2005 WHO guidelines. Children presenting in WHO stage I or II were eligible for ART if CD4 percent was below 20% for children younger than 12 months, below 15% for children under the age of 12 years, or if CD4 count was below 200 cells/mm3 for children older than 12 years. Children presenting at WHO stage III (prior to July 2005) or WHO stage III/IV (July 2005 to June 2006) were eligible irrespective of CD4 percent or CD4 count. First line ART consisted of stavudine, lamivudine and nevirapine for children weighing more than 15 kilograms and zidovudine, lamivudine and nevirapine for those weighing less.
Study participants and data collection
HIV positive children and children exposed to HIV at birth were referred to the clinic from the greater Kinshasa area. All HIV infected children, aged 0 to 18 years that did not have alternative access to ART, are eligible for the SARA project. Data on children aged 0 to 12 years enrolled in the SARA program between November 30, 2004 and May 30, 2006 were analyzed for this study. Clinical and laboratory data collected at baseline were analyzed for all eligible children. Blood samples were collected in the morning and processed the same day at the National HIV Reference Laboratory in Kinshasa. CD4 percent and CD4 count were established using the single platform assay FACSCalibur (Becton Dickinson, Aalst, Belgium). Total lymphocyte count (TLC) was calculated based on WBC count and percent lymphocytes as determined by using the Absorbance Cytochemistry and Volume Technology 5-part differential (ACT 5 diff) hematology analyzer (Coulter Beckman, VWR international, France).
For the purpose of this analysis, we evaluated pediatric ART eligibility using clinical criteria and age-specific immunological criteria recommended in the 2006 WHO guidelines for pediatric ART in resource poor settings (Table 1) [1].
In addition to the CD4 percentage obtained by gold standard flow cytometry, i.e. FACSCalibur assay, we calculated the CD4 percent using the following formula: computed CD4 percent = absolute CD4 count/(WBC count × percentage lymphocytes). The CD4 count used in this computation was obtained by flow cytometry.
Fisher's exact test was used to compare proportions and Kappa (κ) coefficient to assess agreement between ART eligibility criteria. The κ coefficient was interpreted as follows: < 0.20: poor agreement, 0.21 – 0.40: fair agreement, 0.41 – 0.60: moderate agreement, 0.61 – 0.80: substantial agreement, and > 0.80: good agreement [7]. Linear regression was used to determine trends of CD4 percent, CD4 count and TLC across age groups and correlation between CD4 percent measured by flow cytometry and CD4 percent estimate derived through computation. Weight for age z-score was determined using the 1990 British Grow Charts references [8]. Malnutrition was defined as a weight for age z-score of less then minus two. Analyses were performed using STATA version 9.0 (STATA cooperation, Texas, USA).
Ethical approval
All parents of patients signed informed consent for participation, children older than 12 years assented and children older than 8 years received an informational sheet about the study before enrollment. The SARA program was approved by the Institutional Review Boards of the University of North Carolina at Chapel Hill, USA, and the Kinshasa School of Public Health, DRC (IRB reference number 04-MED-168).
A total of 399 HIV infected, ART-naïve children aged 0 to 12 years, were enrolled in the SARA program between November 2004 and June 2006. Thirty-three children were excluded from this analysis because of missing CD4 percent, CD4 count or TLC results at time of enrollment; leaving 366 (91.7%) children for analysis. The median age at baseline was 5 years (Interquartile range (IQR): 1.7 to 8.0 years); the median CD4 percent, CD4 count and TLC by age group are presented in Table 2.
Table 2 Median (Interquartile range, IQR) CD4 percent, CD4 count obtained by flow cytometry and total lymphocyte count by age group.
Comparison of clinical and immunological ART eligibility criteria
At baseline, 196 (53.5%) of 366 children were eligible for ART on clinical grounds (WHO clinical stage III or IV) and 202 (55.2%) were eligible based on any of the age-specific immunological criteria (CD4 percent, CD4 count or TLC). Agreement between clinical and immunological eligibility criteria was poor (κ = 0.26). One third (32.6%, 64/196) of children eligible by clinical criteria were not eligible according to immunological criteria and one third (34.7%, 70/202) of children eligible on immunological criteria were not eligible by clinical criteria. Agreement between clinical and individual immunological criteria was poor to fair, with κ coefficients of 0.29 for CD4 percent, 0.20 for CD4 count and 0.08 for TLC.
Evaluation of immunological criteria
Among children presenting with clinical stage I and II (i.e. ineligible for ART based on clinical criteria), 54/170 (31.8%) were ART eligible by age-specific CD4 percent, 24/170 (14.1%) were ART eligible by age-specific CD4 count and 20/125 (16%) by TLC criteria. Overall, the agreement between CD4 percent and CD4 count thresholds was fair (κ = 0.39), the agreement between CD4 percent and TLC was poor (κ = 0.04) (Table 3). Similar poor to fair agreements were observed across age groups (Table 3). Among children presenting with clinical stage I and II and eligible using CD4 percent thresholds measured by flow cytometry, only 7/38 (18.4%) children age 0 to 8 years would have been eligible using the TLC threshold and one in three (20/54 or 37.0%) children aged 0 to 12 years would have been eligible using CD4 count.
Table 3 Agreement (κ coefficient) using CD4 count obtained by flow cytometry, CD4 percent by computational estimate, and total lymphocyte count (TLC) compared to CD4 percent obtained by flow cytometry for children not eligible for ART on clinical grounds, i.e. WHO stage I or II
Evaluation of the CD4 percent computational estimate
The CD4 percent computational estimate was deemed biologically plausible in the majority (99%, n = 362) of children. In the remaining 1% (n = 4), the calculated CD4 percent was higher than 70%, a value rarely, if ever, observed in vivo, and possibly due to discrepant lymphocyte count obtained by staining and flow cytometry. Excluding the four values deemed implausible, the difference between the computational estimates and CD4 percent obtained by flow cytometry was largest for children with relatively high CD4 percent, and increased by 1.15% (95%CI 1.11 to 1.18, p < 0.01, r2 = 0.91) for every percent increase in CD4 percent obtained by flow cytometry (Figure 1).
CD4 percent obtained by flow cytometry and computational estimate by age group: (A) 0 to 11 months, (B) 12 to 35 months, (C) 36 to 59 months, (D) 60 to 95 months (E) more than 95 months. Grey areas indicate children misclassified using CD4 percent computational estimate compared to CD4 percent obtained by flow cytometry.
Among children presenting in clinical stage I or II, a similar proportion of children was eligible using the two different CD4 percent methods: 52 (31.3%) using CD4 percent obtained by flow cytometry and 53 (31.9%) using CD4 percent computational estimate (p = 0.9). The agreement between results of computational estimates, including those values deemed implausible, and CD4 percent obtained by flow cytometry was good (κ = 0.71) except for children age 35 to 59 months (Table 3).
In asymptomatic children, combining the CD4 computational estimate and CD4 count obtained with flow cytometry would identify 2 extra children eligible for ART treatment.
Cross-sectional baseline CD4 count, CD4 percent and TLC by age
Among children aged 5 to 12 years (n = 186), baseline CD4 count was significantly higher in younger children (-32 cells/mm3 per year, 95%CI -58 to -5, p = 0.02). Similarly, a decrease in TLC was noted with increase in age (-198 cells/mm3 per year, 95%CI -335 to -61, p < 0.01). In contrast, CD4 percent obtained by flow cytometry at (-0.8% per year (95%CI -0.73 to 0.57, p = 0.8) and computational estimate percent (-0.01%, 95%CI -0.97 to 0.77, p = 0.9) remained stable (Figure 2).
Baseline total CD4 count and total lymphocyte count (TLC) decrease with increasing age (p < 0.01). CD4 percent obtained by flow cytometryandcomputational estimate are stable with increasing age (p > 0.05). Linear prediction (and 95%CI) of CD4 percent obtained by flow cytometry (solid line), CD4 percent computational estimate (dashed line), total CD4 count (long dash line) and TLC (long dash – dotted line) in children aged 5 to 12 years.
Performance of the clinical criteria
Similar to experiences in Uganda and Haiti, approximately half of the children in our DRC cohort were eligible for ART at first presentation, likely due to late care-seeking and the recent introduction of free ART in these settings [9, 10].
The agreement between the WHO clinical stages and immunological thresholds for ART eligibility was fair for CD4 percent but poor for total CD4 count and TLC. Approximately one third of children eligible for ART using immunological criteria were not eligible using clinical criteria. ART eligibility decision making on clinical grounds only would thus delay ART initiation in these children until they become symptomatic. Delay in ART initiation could lead to death in young infants who progress rapidly. Delayed ART initiation also impacts negatively immunological recovery following ART initiation, as patients with a low CD4 lymphocyte nadir have a slower increases in CD4 count, prolonging the period at risk of opportunistic infections [11]. Furthermore, when ART is started in children with less than 5% CD4 percent, levels of CD4 rarely reach normal levels [12].
Up to 30% of symptomatic children (WHO clinical stage III or IV) were not eligible for ART using immunological criteria. Children in Sub Saharan Africa are exposed to more infectious agents compared to children in industrialized countries. The high incidence of tuberculosis, bacterial dysentery, recurrent pneumonia and malnutrition may have resulted in a high proportion of children classified in WHO stages III/IV despite a relatively good immune system. Consequently, some children classified as clinical WHO stage III/IV could start ART "too early", if their symptoms are not the consequence of immunosuppression, but rather the result of environmental exposure. This was also observed in Tanzania by Johnson et al, who reported a sensitivity of 72% and a specificity of 56% of WHO clinical stage III/IV to detect severe immunosuppression in HIV positive children and has also been observed in adult populations [13, 14]. In Cambodia, the 2003 WHO clinical criteria had a sensitivity of 96%, but an equally low specificity of 57% to identify patients in need of ART [14].
Because CD4 count and percentage only assess the level of immune suppression in a quantitative manner, not qualitatively, it would be imprudent to delay ART in children eligible based on clinical criteria. Results of the 3Cs4Kids a meta-analysis untreated HIV infected children in resource poor settings, showed that malnutrition, hemoglobin and WHO stage III or IV disease, are associated with high mortality independent of CD4 percentage or count, underscoring that ART should not be delayed in children with these conditions [15].
Performance of the immunological criteria
Understanding the correlations between CD4 count, TLC, and CD4 percent is important in settings where access to the gold standard CD4 percent assay is limited. In our study, agreement between CD4 percent and total CD4 count or TLC was poor. Among children presenting in clinical stage I and II, only one third of children eligible according to CD4 percent criteria were eligible using total CD4 count, and only one in five children eligible based on CD4 percent were eligible according to TLC criteria. The CD4 percent computational estimate correlated better with the CD4 percent obtained by flow cytometry. More than 80% of ART children eligible according to the CD4 percent obtained by flow cytometry were also eligible using CD4 percent computational estimate. Use of the CD4 percent computational estimate could thus represent a substantial improvement compared to CD4 count. Moreover, it is an easy method, which can be implemented with limited extra cost beyond the cost of CD4 count, i.e. the cost to determine the total white blood cell count and lymphocyte percentage. Furthermore, the use of the CD4 percent computational estimate could facilitate decentralization of pediatric ART in centers without the access to flow cytometry, which may result in decreased indirect costs such as time off work and transportation cost.
Because a smaller proportion of children is eligible according to CD4 count compared to CD4 percent, relying on CD4 count for ART eligibility screening could delay ART initiation in up to 30% of children, exposing them to prolonged risk of acquiring opportunistic infections, disease progression or death. As the current WHO criteria are based on US en European data, the underestimation of children eligible for ART based on immunological criteria may be even more pronounced in sub-Saharan African settings, as genetic and environmental factors, which may influence immunity, are currently not taken into account in the WHO classification [15, 16].
Decline of CD4 count in children older than 5 years
WHO recommends the use of total CD4 count for ART eligibility screening in children older than 5 years. Similar to findings in Ugandan and Kenyan HIV negative children [5, 6], CD4 count in HIV infected children in our study continued to decrease between the ages of 5 and 12 years. In contrast, both the CD4 percents measured by flow cytometry and the computational estimates were stable across age groups. Using CD4 count alone from the age of 5 might thus underestimate the number of children eligible for ART.
Study Limitations
Several limitations to this study should be noted. To calculate the CD4 percent using the simple formula, we used the CD4 count as determined by flow cytometry, and although the lymphocytes were determined using an automated complete blood count (CBC) method using staining methods and not flow cytometry, the technique used is also automated and may be too costly in many settings. While others have demonstrated that low cost CD4 assays correlate well with the FACSCalibur assay [17, 18], the use of the CD4 count obtained by flow cytometry may have resulted in an overestimation of the correlation of the CD4 percent computational estimates with the CD4 percent measured by flow cytometry. Prior to recommending the use of this formula in resource poor settings, the validity of this computational approach should therefore be evaluated using WBC count, percentage lymphocytes and CD4 count obtained through low cost (non flow-based) assays. Second, the finding that baseline CD4 count and TLC decreased with increasing age was based on cross sectional data analysis and not on longitudinal follow up of children. The observed decrease could also be due to increased immunosuppression with increasing age. However, one would then also expect a decreasing CD4 percent with age, whereas our data demonstrated stable CD4 percent values across the 5–12 years age group. Lastly, the value of different ART eligibility criteria would ideally be determined by their correlation with risk of death or disease progression, as in cohort studies conducted in European and USA in the early stage of the AIDS epidemic. Clearly, in light of the effectiveness of and increasing access to ART, such cohort studies can no longer be performed. The 3Cs4Kids meta-analysis showed that, compared to children in Europe and the US, children in resource limited settings have a higher 12-month risk of death at any level of CD4 percentage or count. However, this study could not determine whether this increased risk was attributable to immunosuppression or other factors, such as the higher mortality seen in severely malnourished children [15]. In contrast, trials, such as the CHER and PREDICT trial, establishing the impact of early ART initiation in children, might generate useful data on optimal timing of ART [19, 20].
CD4 percent is the most appropriate immunological criterion to screen HIV infected children, aged 0 to 12 years, for ART eligibility. CD4 percent will identify the highest proportion of children at early stages of immunosuppression. CD4 count and TLC may be less appropriate as the proposed WHO thresholds for total CD4 count and TLC do not correspond well with CD4 percent, CD4 counts decrease with increasing age, and using total CD4 count or TLC underestimates the number of children eligible for ART. Where access to CD4 percent assays is not available, CD4 percent obtained with a simple formula based on total white blood count, lymphocyte percent and total CD4 count may improve the identification of children in need of treatment in resource poor settings.
Antiretroviral therapy of HIV infection in infants and children in resource-limited settings: towards universal access. Recommendations for a public health approach. [http://www.who.int/hiv/pub/guidelines/paediatric020907.pdf]
Walker AS, Mulenga V, Sinyinza F, Lishimpi K, Nunn A, Chintu C, Gibb DM: Determinants of survival without antiretroviral therapy after infancy in HIV-1-infected Zambian children in the CHAP Trial. J Acquir Immune Defic Syndr. 2006, 42 (5): 637-645. 10.1097/01.qai.0000226334.34717.dc.
HIV Paediatric Prognostic Markers Collaborative Study: Use of total lymphocyte count for informing when to start antiretroviral therapy in HIV-infected children: a meta-analysis of longitudinal data. Lancet. 2005, 366 (9500): 1868-1874. 10.1016/S0140-6736(05)67757-4.
Bachou H, Tylleskar T, Downing R, Tumwine JK: Severe malnutrition with and without HIV-1 infection in hospitalised children in Kampala, Uganda: differences in clinical features, haematological findings and CD4+ cell count. Nutr J. 2006, 5 (1): 27-10.1186/1475-2891-5-27.
Lugada ES, Mermin J, Kaharuza F, Ulvestad E, Were W, Langeland N, Asjo B, Malamba S, Downing R: Population-based hematologic and immunologic reference values for a healthy Ugandan population. Clin Diagn Lab Immunol. 2004, 11 (1): 29-34. 10.1128/CDLI.11.1.29-34.2004.
Embree J, Bwayo J, Nagelkerke N, Njenga S, Nyange P, Ndinya-Achola J, Pamba H, Plummer F: Lymphocyte subsets in human immunodeficiency virus type 1-infected and uninfected children in Nairobi. Pediatr Infect Dis J. 2001, 20 (4): 397-403. 10.1097/00006454-200104000-00006.
Landis JR, Koch GG: The measurement of observer agreement for categorical data. Biometrics. 1977, 33 (1): 159-174. 10.2307/2529310.
Freeman JV, Cole TJ, Chinn S, Jones PR, White EM, Preece MA: Cross sectional stature and weight reference curves for the UK, 1990. Arch Dis Child. 1995, 73 (1): 17-24.
Sengoba J, Awori M, Blackham J, Sims R: Why are children still dying? [CDB0053]. Presented at: XVI International AIDS Conference: 2006; Toronto, Canada. 2006
Pierre R, Steel-Duncan J, Evans-Gilbert T, Rodriguez B, Moore J, Palmer P, Smikle M, Davis D, Figueroa J, Christie C, et al: Effectiveness of interventions in treating paediatric HIV/AIDS in Jamaican children [CDB1017]. Presented at: XVI International AIDS Conference: 2006; Toronto, Canada. 2006
Kaufmann GR, Perrin L, Pantaleo G, Opravil M, Furrer H, Telenti A, Hirschel B, Ledergerber B, Vernazza P, Bernasconi E, et al: CD4 T-lymphocyte recovery in individuals with advanced HIV-1 infection receiving potent antiretroviral therapy for 4 years: the Swiss HIV Cohort Study. Arch Intern Med. 2003, 163 (18): 2187-2195. 10.1001/archinte.163.18.2187.
Resino S, Correa R, Bellon JM, Sanchez-Ramon S, Munoz-Fernandez MA: Characterizing immune reconstitution after long-term highly active antiretroviral therapy in pediatric AIDS. AIDS Res Hum Retroviruses. 2002, 18 (18): 1395-1406. 10.1089/088922202320935474.
Johnson OO, Benjamin DK, Schimana W, Benjamin DK, Landman K, Tillekeratne LG, Crump JA, Kinabo GD, Swai M, Shao JF, et al: Absolute lymphocyte count and WHO pediatric clinical stage as markers to assess need to initiate antiretroviral therapy among HIV-infected children in northern Tanzania [MOPE0100]. Presented at: XVI International AIDS Conference: 2006; Toronto, Canada. 2006
Lynen L, Teav S, Vereecken C, De Munter P, An S, Jacques G, Kestens L: Validation of primary CD4 gating as an affordable strategy for absolute CD4 counting in Cambodia. J Acquir Immune Defic Syndr. 2006, 43 (2): 179-185. 10.1097/01.qai.0000242447.82403.c2.
3Cs4kids Analysis and Writing Committee: Markers for predicting mortality in untreated HIV-infected children in resource-limited settings: a meta-analysis. Aids. 2008, 22 (1): 97-105.
Bunders M, Lugada E, Mermin J, Downing R, Were W, Thorne C, Newell ML: Within and between race differences in lymphocyte, CD4+, CD8+ and neutrophil levels in HIV-uninfected children with or without HIV exposure in Europe and Uganda. Ann Trop Paediatr. 2006, 26 (3): 169-179. 10.1179/146532806X120255.
Dieye TN, Vereecken C, Diallo AA, Ondoa P, Diaw PA, Camara M, Karam F, Mboup S, Kestens L: Absolute CD4 T-cell counting in resource-poor settings: direct volumetric measurements versus bead-based clinical flow cytometry instruments. J Acquir Immune Defic Syndr. 2005, 39 (1): 32-37. 10.1097/01.qai.0000160515.20581.ad.
Pattanapanyasat K, Lerdwana S, Noulsri E, Chaowanachan T, Wasinrapee P, Sakulploy N, Pobkeeree V, Suksripanich O, Thanprasertsuk S, Spira TJ, et al: Evaluation of a new single-parameter volumetric flow cytometer (CyFlow(green)) for enumeration of absolute CD4+ T lymphocytes in human immunodeficiency virus type 1-infected Thai patients. Clin Diagn Lab Immunol. 2005, 12 (12): 1416-1424. 10.1128/CDLI.12.12.1416-1424.2005.
Violari A, Cotton M, Gibb D, Babiker A, Steyn J, Jean-Phillip P, McIntyre J, Team obotCS: Antiretroviral therapy initiated before 12 weeks of age reduces early mortality in young HIV-infected infants: evidence from the Children with HIV Early Antiretroviral Therapy (CHER) Study [CDB0037]. Presented at: 4th IAS Conference on HIV Pathogenesis, Treatment and Prevention: 2007; Sydney, Australia. 2007
Puthanakit T, Ananworanich J, Kosalaraksa P, Hansudewechakul R, Chuenyam T, Chettra K, Saphonn V, Chhi Vun M, Cooper D, Fox L, et al: A randomized trial of early versus deferred initiation of antiretroviral therapy (ART) in HIV-infected children with moderate immune suppression in Cambodia and Thailand: the PREDICT study [CDB225]. Presented at: 4th IAS conference on HIV Pathogenesis, Treatment and Prevention: 2007; Sydney, Australia. 2007
Funding was provided by the Centers for Disease Control and Prevention Global AIDS Program (CDC U62/CCU422422). The content of this report does not necessarily reflect the views or opinions of the funding agency. The authors thank the SARA team, Ms Karen Hawkins Reed and Mr Kashamuka Mwandagalirwa for crucial support.
Department of Epidemiology, School of Public Health, University of North Carolina, Chapel Hill, USA
Steven FJ Callens, Frieda Behets & Annelies Van Rie
School of Public Health, University of Kinshasa, Congo
Faustin Kitetele, Jean Lusiama & Nicole Shabani
National AIDS Reference Laboratory, Kinshasa, Congo
Samuel Edidi
Institute of Tropical Medicine, Antwerp, Belgium and University of Antwerp, Belgium
Robert Colebunders
Steven FJ Callens
Faustin Kitetele
Jean Lusiama
Nicole Shabani
Frieda Behets
Annelies Van Rie
Correspondence to Steven FJ Callens.
SC wrote the manuscript; FK and JL coordinated the SARA project, collected data and reviewed the manuscript; SE performed the laboratory assays and reviewed the manuscript; RC, FB and AVR provided scientific input in the discussion of the article. All authors read and approved the final manuscript.
This article is published under license to BioMed Central Ltd. This is an Open Access article distributed under the terms of the Creative Commons Attribution License (http://creativecommons.org/licenses/by/2.0), which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited.
Callens, S.F., Kitetele, F., Lusiama, J. et al. Computed CD4 percentage as a low-cost method for determining pediatric antiretroviral treatment eligibility. BMC Infect Dis 8, 31 (2008). https://doi.org/10.1186/1471-2334-8-31
Received: 08 November 2007
Resource Poor Setting
Total Lymphocyte Count
Total White Blood Cell Count
Immunological Criterion
Immunological Threshold


Offered by RC Willey, the Madison Ridge 4 piece California king bedroom set is grand in both scale and beauty.
Its stately moldings, charming detailing, and superior craftsmanship make it an ideal choice for those looking to add timeless, traditional appeal to their living spaces. You're sure to love its convenient features like lift-top storage in the footboard and USB outlet in the nightstand just as much as you'll adore its durability and enduring design.
Includes headboard, storage footboard, rails, slats, dresser, mirror, and nightstand.
The Madison Ridge California king storage bed, now at RC Willey, is grand in both scale and beauty! Its stately moldings, charming detailing, and superior craftsmanship make it an ideal choice for those looking to add timeless, traditional appeal to their living spaces. You're sure to love its convenient features like lift-top storage just as much as you'll adore its durability and enduring design.
The Madison Ridge 10-drawer dresser is grand in both scale and beauty and RC Willey has it! You're sure to love its convenient, plentiful storage just as much as you'll adore its durability and enduring design. Its stately moldings, charming detailing, and superior craftsmanship make it an ideal choice for those looking to add timeless, traditional appeal to their living spaces.
The Madison Ridge nightstand at RC Willey is grand in both scale and beauty. You're sure to love its convenience with its USB outlet and 3 drawers just as much as you'll adore its durability and enduring design. Its stately moldings, charming detailing, and superior craftsmanship make it an ideal choice for those looking to add timeless, traditional appeal to their living spaces.


text:
import praw
import re
import os
import datetime
import urllib
import shutil

WALLPAPER_DIR = "/Users/Seb/Documents/Privat/Code/Python/Wallpaper_Daily_Manager/DailyWallpapers/"
BASE_DIR = "/Users/Seb/Documents/Privat/Code/Python/Wallpaper_Daily_Manager/"
SUB = 'EarthPorn'
NUM_IMAGES = 11

def getNameFromURL(url):
    url = str(url)
    match = re.search("https?\:\/{2}.+\/(.+\.[jpng]{3})$",url)
    return str(match.group(1))

def downloadImages(url_list, toDir='.'):
    r = urllib.URLopener()
    for url in url_list:
        if(not(os.path.exists(str(toDir + '/' + getNameFromURL(url))))):
            try:
                r.retrieve(url, str(toDir) + '/' + getNameFromURL(url))
            except Exception as e:
                print e
                print("Could not downlad image from %s"%url)
        else:
            pass

# Read client_id and client_secret from file and add to list
with open("/Users/Seb/Documents/Privat/Code/Python/Wallpaper_Daily_Manager/credentials.cfg") as c:
    credentials = c.readlines()

credentials = [x.strip() for x in credentials]

# Connect to reddit using client_id and client_secret read from file
# client_id and client_secret is provided by Reddit
try:
    reddit = praw.Reddit(
        client_id=credentials[0],
        client_secret=credentials[1],
        user_agent=credentials[2]
        )
except Exception as e:
    print e
    print "Could not connect to Reddit! Program shutting down!"
    exit()

# Store the URL of the top 5 images in 'hot'
# Gets the first six posts because the first one is a stickied self-post
urls = []
try:
    for post in reddit.subreddit(SUB).hot(limit=NUM_IMAGES):
        if(not(post.stickied)):
            if(str(post.url).endswith(".jpg") or str(post.url).endswith(".png")):
                urls.append(post.url)
except Exception as e:
    print e
    print "Could not connect! Program shutting down!"
    exit();

imgdir = BASE_DIR  + str(datetime.date.today())

# Make a directory for today
try:
    os.mkdir(imgdir)
except OSError:
    pass

# Download the images into the created dir
try:
    downloadImages(urls, imgdir)
except Exception as e:
    print e
    print "Could not connect! Program exiting!"
    exit()

# Copy images into DailyWallpapers

for f in os.listdir(WALLPAPER_DIR):
    f_path = os.path.join(WALLPAPER_DIR, f)
    try:
        if os.path.isfile(f_path):
            os.unlink(f_path)
    except Exception as e:
        print e

for img in os.listdir(imgdir):
    oldpath = os.path.join(imgdir,img)
    newpath = os.path.join(WALLPAPER_DIR, img)
    try:
        if os.path.isfile(oldpath):
            shutil.copyfile(oldpath, newpath)
    except Exception as e:
        print e

redpajama_set_name: RedPajamaGithub


Compare at $4,000.00. You Save $200.00!
When I say this Chanel Deauville Tote is Extra Large, I mean it's so big, a flight attendant might question its size as a carry-on! But, no worries, it will definitely fit in an overhead bin. It's made of black Caviar leather with silver hardware and feet, and the front face is emblazoned with the CC logo and "Chanel Paris" in silver studs. The open top secures with a hidden magnetic closure and, in black fabric lining inside, you'll find two zipped pockets and a key leash. Carry this tote by the dual handles with a 4-inch drop or over the shoulder by the leather-through-chain strap with a 13-inch drop and an all-leather top for comfort. In excellent condition from 2018, it comes with a dustbag, box, and card and has a few marks on the leather. Don't limit this structured bag to traveling, it's got the goods for work, play, shopping, even the gym!


text:
A Trail of Two Bridges
This walk is based on Barnstaple and uses both old bridge and new to form a circuit. The two bridges are linked by using the line of the South West Coast Path on either side of the river; this path has traditionally come upriver to Barnstaple to use the crossing. This part of the Coast Path is also used by the Tarka Trail, a 180 mile figure of eight route throughout northern Devon with Barnstaple at its hub which follows the wanderings of Tarka the Otter in the book of that name. This part of the Tarka Trail is also well surfaced and gradients are gentle, so this walk is usable by wheelchairs, buggies and pushchairs.
The Tarka Trail (Braunton – Meeth)
Tarka, the Taw and a Town Trail
Tarka Trail walking route
Barnstaple is the centre for public transport in North Devon, with bus services from all over the area as well as Exeter and Plymouth.
In addition, Barnstaple is at the end of the Tarka Line branch railway from Exeter.
Barnstaple - all facilities.
No stiles; one short and gentle gradient.
Landranger (1:50,000 scale) no. 180 Barnstaple and Ilfracombe.
Explorer (1:25,000 scale) no. 139 Bideford, Ilfracombe and Barnstaple
Barnstaple is an historic and attractive town as well as the centre of population in North Devon. One of Devon's ancient Saxon settlements, which even had its own mint the 10th century, it was listed in the Domesday Book of 1086 as one of the four boroughs of Devon. The town was established at the lowest crossing point of the River Taw, and a bridge was established here in early times. The current town bridge originated in the early 13th century but very recently this has been augmented by a new bridge downstream. For the first time since it was built some 800 years ago Barnstaple's ancient bridge is no longer the lowest bridging point over the river.
The Museum is in The Square, at the town end of the old Barnstaple Bridge. In the middle of The Square is the Albert Memorial Clock, erected to commemorate the life of Queen Victoria's consort in 1862.
The area on the right was originally a natural inlet and then became Barnstaple's Quay area. It was from here that five ships sailed to join Drake's fleet to fight the Spanish Armada in 1588. Barnstaple remained an important port until the early 19th century, when the increasing size of ships and silting of the river combined to end its trade. The Quay area was then filled in.
The site of the old Barnstaple Town railway station, served the line of the Atlantic Coast Express to Ilfracombe and was also the terminus of the Lynton and Barnstaple Railway. This was a narrow gauge line which operated between 1898 and 1935. A thriving Society exists to promote the history and knowledge of this railway and has reopened a short stretch of the old line, together with the historic station, at Woody Bay near Lynton.
There are actually three bridges to be crossed on this walk, this being the smallest of the three. Shaped like a boat, it spans the end of the River Yeo, a tributary of the Taw which comes down from the edge of Exmoor. A swing bridge is needed in case river traffic needs to reach Rolle Quay, a little way up the Yeo.
The Coast Path and Tarka Trail here is on the line of the old railway to Ilfracombe. Built in 1874 it became an important tourist line, carrying the Ilfracombe portion of the Atlantic Coast Express from Waterloo. It was closed in 1970.
The bridge was opened in May 2007 to link the main A39 road to the road to Braunton and Ilfracombe, avoiding the town centre of Barnstaple. Sometimes referred to as the Western Bypass it has been designed to reduce, as far as possible, any damage to the environment.
The Taw Estuary is a designated Site of Special Scientific Interest and the protection of the estuary during and after construction has therefore been important. The impact of noise and disturbance on the estuary's wildlife and habitats has been minimised and a variety of measures taken to protect otters and badgers and preserve and enhance habitats for bats and barn owls. New habitats are also being created, including grassland, hedgerows and wetlands.
The bridge offers an excellent viewpoint for looking down the river, the marshes framing the estuary as it curves down towards the mouth. Unless the tide is high, the effect of silting which spelled the end of Barnstaple as a port will be seen in the numerous sandbanks.
The bridge may now be used as a shortcut across the river by walkers on the South West Coast Path and walkers or cyclists on the Tarka Trail. It is an exciting experience, probably unique on the whole 630 miles of the Coast Path, although it does mean missing the facilities Barnstaple has to offer unless a diversion into the town is made.
This bridge was originally built in the 13th century. It underwent improvements in the 1430s and the 1580s and was last widened in the 1960s. It has 16 stone arches, 13 of them medieval and the other three, at the town end, replaced in 1589.
Barnstaple Clock Tower Copyright Dietmar Rabich
Long walks
32miles/
Stretching for over 52km / 32 miles from Braunton to Barnstaple, then to Instow, Bideford, Great Torrington and on to
Barnstaple and Bideford
This is a one-way walk along the old railway line which flanks the south side of the Taw Estuary in
long-walks
163miles/
Inspired by Henry Williamson's much loved novel 'Tarka the Otter' which was based on real places, this 163 miles/261kms recreation
Braunton to Meeth (via Barnstaple)

redpajama_set_name: RedPajamaCommonCrawl


1.350 exhibitors from 100 countries – Eurobike is not only more beautiful, but also more international than last year. But this is not enough for the makers of Eurobike in Friedrichshafen: Only a happy exhibitor is a good exhibitor. That this goal was reached as well is demonstrated in the following clip.


There are currently 52,879 users on this website.
I drew out the lines in in the date that I'm questioning. Just trying to get a fell for what they are?
Interesting. Photos can be a bit tough to interpret, but could be something going on there. Not too different looking than WDDO-002 although the die scratches don't match and the mint mark may be a bit too far west. Looking at the top corners of TRUST to see if anything is going on there would be useful.
To me it looked like machining but on the date it looks like there's a "flap" of metal over the base of the zero. and a line up the base of the seven.
Nothing good going on there at TRUST, so there is that. Honestly can't say for sure what's going on with the date, but try putting a couple layers of tissue or something over your light to create a diffuser and cut the glare. Maybe something pops out, maybe it doesn't. Looks like a nice coin either way.
Good Call. Thanks for the tip.
You should include the date, mintmark, and the denomination in your titles.
This enables the members with expertise pertaining to your question to easily find and answer your question. The title of the topic also becomes the title of the topic's web page, which enables us to attract more collectors to the site. The more members we have, the more we learn.
I couldn't find a match on the sites for this die yet. I need to make a side by side to see if the devices are enlarged or not. So keep it safe for now.
Looks like a bit of doubling on the '7' and possibly the 'O'. So I would get a better image of just that area and any other areas where doubling could happen. Then Submit it to John Wexler and see what he thinks. The notches on the '7' are real convincing, but the spread is not huge.
Wow!! How cool. I just thought I was seeing things... Holy crap!! I knew something was up when it didn't get resolved right away.
Any Idea if its the real deal what it might be worth? Honestly, I couldn't even wager a guess.
Thanks so much. I'll get the pics done today.
If accepted and listed as a new doubled die by Wexler, it would be WDDO-054. As in, there are already 53 known doubled dies for 1970-S making it one of the years with rather a lot of them (Tanman found the last one so big congrats to him!). That tends to lower the value of any particular one. It could be expected that your coin, if accepted and used as the plate coin on the website, would value around $25 although understand that is a guess based on selling a lot of cud plate coins not DDO plate coins. The value goes up a bit if he gives it "best of" label.
But it maybe a case of MD altering the digits on the date? So don't get your hopes up too high yet.
His email address is on the lower part of the home page.
It took 0.98 seconds to rattle this change.


text:
Wolves agree deal for Spain and Paris St Germain midfielder Pablo Sarabia
Spain international Pablo Sarabia is set to join Wolves pending a medical on Tuesday (Adam Davy/PA) (PA Wire)
Wolves have agreed the signing of attacking midfielder Pablo Sarabia from Paris St Germain, the PA news agency understands.
The Spain international is set to join on a two-and-a-half-year deal for a fee of five million euros (£4.4million).
The deal is subject to Sarabia passing a medical on Tuesday.
The 30-year-old has made 14 Ligue 1 appearances for PSG so far this season, all but three off the bench, and also featured in three Champions League games.
He joined PSG from Sevilla in 2019 and was part of Spain's squad for the 2022 World Cup in Qatar.
Wolves boss Julen Lopetegui had been coy about any new signings at his press conference earlier on Monday, refusing to discuss any incoming transfers ahead of Tuesday's FA Cup replay with Liverpool.
Flamengo midfielder Joao Gomes is also a target, with Wolves having already signed Matheus Cunha on an initial loan from Atletico Madrid.
"We will see, it's true we have interest in some players, but when they are here and our players we can talk about them, not before," said Lopetegui.
It's true we have interest in some players, but when they are here and our players we can talk about them, not before
"I want to put the focus on our players. We don't want to waste energy on other things. We will talk only about our players."
Wolves were furious after Toti Gomes' goal was ruled out for a controversial offside in the 2-2 draw at Anfield, with the club writing to referees' chief Howard Webb to ask for an explanation.
Diego Costa could return to the squad after missing Saturday's Premier League victory over West Ham, while Sasa Kalajdzic (knee), Boubacar Traore (groin) and Pedro Neto (ankle) are out.
"Liverpool are one of the best teams in the world," added Lopetegui. "The quality of his (Jurgen Klopp) players, the coach, his history.
"I'm sure they're going to come here and look to do a big match. We have to be ready to overcome them.
"The FA Cup is going to be an important aim for them – us too – we have to fight to overcome one of the best teams in the world.
"It's more or less the same (how Wolves deal with Liverpool following the original draw), maybe they can change something but we only focus on what we want to do.
"When you play every three days it's not a lot of time to prepare so you have to balance the time to be able to work with the team."


After months of being pregnant, it's time to shower and celebrate the future mommy! Why not choose an invitation that truly reflects her!?
This invitation is part of our customizable illustration collection. You are able to change the skin color, hair color and hairstyle to reflect the honoree.
If you need a helping hand, we're here to help with layout, colors, photo editing, and etiquette advice. We even send you a free digital proof. You can request edits by choosing "request free designer assistance" at the end of personalization.


text:
Foursquare Revenue Plan
Despite Foursquare's garnering a $600 million valuation in an investment round last year, some investors are skeptical about its prospects. Others just seem to find the app and the whole concept of checking in every place they go annoying.
Foursquare has come up with an interesting concept of awarding badges, mayor ship and sharing that has made the app very popular among users and has made the company growth study and solid. The company founder and CEO Dennis Crowley has over 100 employees and is described as a very hands on CEO.
The three year old company has a user base of 20 million people who have accumulated over two billion check ins. The company has over 750,000 businesses that use the platform companies by the name of Pepsi, Walgreens and American Express just to name a few. The company has been competing with Instagram, Facebook (FB), Groupon (GRPN), andYelp (YELP).
Foursquare is looking at using coupons as a form of revenue. This will require some tweaking of there app to help point users toward those places that they have checked in or other friends have checked in. They have made changes to there app for recommendations that are tailored to the individual.
Foursquare has a lot of work a head of it now that they have built there user base they need to focus on making revenue. The biggest problem with any .com company is making sure they have a revenue stream. After 3 long years Foursquare as a company knows they need to produce a revenue stream or investors will pull out. The revenue stream will also be important if the company decides to take the company public with the latest .com IPO boom. For Foursquare I hope they are able to compete and continue on against composition and revenue issues in the future of there business.
BusinessDennis CrowleyFoursquareFoursquare RevenueFoursquare Revenue PlanIPO - by admin
Pandora Revenue and Business Model
Enable Remote Desktop on UAG Server


text:
Balentine Grows Leadership Team with Partner Promotion
Relationship Manager and Head of Financial Planning in the firm's Raleigh office takes on expanded leadership role
Raleigh, N.C. — Balentine announced today that John Maddison, CFA, CFP® has been promoted to partner at the rapidly growing wealth management firm serving entrepreneurs and business owners. Since Maddison joined Balentine at its Raleigh office in 2014, he has delivered tremendous value to clients and colleagues as demonstrated by his financial acumen, attention to detail, and client-first work ethic. In addition, Maddison spearheaded the creation of the Balentine Blueprint™, a proprietary financial planning methodology at the core of the solutions provided to clients every day. These efforts have catapulted Balentine's presence in North Carolina to nearly $1B in assets from core clients in the Carolinas, the east coast and overseas.
"John has been a critical contributor to nurturing some of our most comprehensive relationships. Simply stated, John lives Balentine's values every day," said Rob Ragsdale, Partner and Head of the Raleigh office. A Raleigh native, Maddison earned a BA and MBA from the University of North Carolina at Chapel Hill and has more than 17 years of experience working in the financial services industry serving corporate, institutional, and private clients. "In many firms, the biggest competition is sitting in the office beside you. At Balentine, the emphasis is on truly providing the best and most objective advice available to our clients," said John Maddison.
Maddison is also very involved with the community. He has served two terms as president of CFA Society North Carolina and was named Volunteer of the Year in 2016 for his leadership and vision. He's an active member of the Vestry and Investment Committee of Christ Church Raleigh, the Board of Directors for the Council for Entrepreneurial Development (CED), and the Investment Committee of YMCA of the Triangle in addition to volunteering with Band Together and various youth sports.
Since Balentine was founded in 2009, the firm's staff has doubled to 35 professionals, assets under advisement have grown to $2.7 billion, and it has opened an office in Raleigh that has earned enthusiastic market acceptance.
About Balentine
Balentine is an employee-owned financial management firm headquartered in Atlanta, Georgia, with a second office in Raleigh, North Carolina. Offering comprehensive wealth management services for families and global asset allocation strategies for institutions, Balentine seeks to deliver an exceptional client experience in addition to consistent long-term investment results. For 30 years, the Balentine legacy has been one of innovation, service to clients, and service to the community. Forbes, Barron's, Financial Times, and InvestmentNews have recognized Balentine as a top financial planning and advisory firm. Balentine is a registered investment advisor with the Securities and Exchange Commission.
Chairman's Message: We're Not in the Same Boat
Balentine News, Business Owners, U.S. Markets & Economics
Webinar Recording: Market Watch with CEO Adrian Cronje | March 27, 2020
Balentine News, Portfolio Management, Risk Management, U.S. Markets & Economics
Balentine News, U.S. Markets & Economics


text:
"""Implementation of a backup service that uses Swift as the backend

**Related Flags**

:backup_swift_url: The URL of the Swift endpoint (default: None, use catalog).
:swift_catalog_info: Info to match when looking for swift in the service '
                     catalog.
:backup_swift_object_size: The size in bytes of the Swift objects used
                                    for volume backups (default: 52428800).
:backup_swift_retry_attempts: The number of retries to make for Swift
                                    operations (default: 10).
:backup_swift_retry_backoff: The backoff time in seconds between retrying
                                    failed Swift operations (default: 10).
:backup_compression_algorithm: Compression algorithm to use for volume
                               backups. Supported options are:
                               None (to disable), zlib and bz2 (default: zlib)
"""

import hashlib
import json
import os
import socket

import eventlet
from oslo_config import cfg
from oslo_utils import excutils
from oslo_utils import timeutils
from oslo_utils import units
import six
from swiftclient import client as swift

from cinder.backup.driver import BackupDriver
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.openstack.common import log as logging
from cinder.openstack.common import loopingcall
from cinder.volume import utils as volume_utils

LOG = logging.getLogger(__name__)

swiftbackup_service_opts = [
    cfg.StrOpt('backup_swift_url',
               default=None,
               help='The URL of the Swift endpoint'),
    cfg.StrOpt('swift_catalog_info',
               default='object-store:swift:publicURL',
               help='Info to match when looking for swift in the service '
               'catalog. Format is: separated values of the form: '
               '<service_type>:<service_name>:<endpoint_type> - '
               'Only used if backup_swift_url is unset'),
    cfg.StrOpt('backup_swift_auth',
               default='per_user',
               help='Swift authentication mechanism'),
    cfg.StrOpt('backup_swift_auth_version',
               default='1',
               help='Swift authentication version. Specify "1" for auth 1.0'
                    ', or "2" for auth 2.0'),
    cfg.StrOpt('backup_swift_tenant',
               default=None,
               help='Swift tenant/account name. Required when connecting'
                    ' to an auth 2.0 system'),
    cfg.StrOpt('backup_swift_user',
               default=None,
               help='Swift user name'),
    cfg.StrOpt('backup_swift_key',
               default=None,
               help='Swift key for authentication'),
    cfg.StrOpt('backup_swift_container',
               default='volumebackups',
               help='The default Swift container to use'),
    cfg.IntOpt('backup_swift_object_size',
               default=52428800,
               help='The size in bytes of Swift backup objects'),
    cfg.IntOpt('backup_swift_retry_attempts',
               default=3,
               help='The number of retries to make for Swift operations'),
    cfg.IntOpt('backup_swift_retry_backoff',
               default=2,
               help='The backoff time in seconds between Swift retries'),
    cfg.StrOpt('backup_compression_algorithm',
               default='zlib',
               help='Compression algorithm (None to disable)'),
    cfg.BoolOpt('backup_swift_enable_progress_timer',
                default=True,
                help='Enable or Disable the timer to send the periodic '
                     'progress notifications to Ceilometer when backing '
                     'up the volume to the Swift backend storage. The '
                     'default value is True to enable the timer.'),
]

CONF = cfg.CONF
CONF.register_opts(swiftbackup_service_opts)

class SwiftBackupDriver(BackupDriver):
    """Provides backup, restore and delete of backup objects within Swift."""

    DRIVER_VERSION = '1.0.0'
    DRIVER_VERSION_MAPPING = {'1.0.0': '_restore_v1'}

    def _get_compressor(self, algorithm):
        try:
            if algorithm.lower() in ('none', 'off', 'no'):
                return None
            elif algorithm.lower() in ('zlib', 'gzip'):
                import zlib as compressor
                return compressor
            elif algorithm.lower() in ('bz2', 'bzip2'):
                import bz2 as compressor
                return compressor
        except ImportError:
            pass

        err = _('unsupported compression algorithm: %s') % algorithm
        raise ValueError(unicode(err))

    def __init__(self, context, db_driver=None):
        super(SwiftBackupDriver, self).__init__(context, db_driver)
        if CONF.backup_swift_url is None:
            self.swift_url = None
            info = CONF.swift_catalog_info
            try:
                service_type, service_name, endpoint_type = info.split(':')
            except ValueError:
                raise exception.BackupDriverException(_(
                    "Failed to parse the configuration option "
                    "'swift_catalog_info', must be in the form "
                    "<service_type>:<service_name>:<endpoint_type>"))
            for entry in context.service_catalog:
                if entry.get('type') == service_type:
                    self.swift_url = entry.get(
                        'endpoints')[0].get(endpoint_type)
        else:
            self.swift_url = '%s%s' % (CONF.backup_swift_url,
                                       context.project_id)
        if self.swift_url is None:
            raise exception.BackupDriverException(_(
                "Could not determine which Swift endpoint to use. This can "
                " either be set in the service catalog or with the "
                " cinder.conf config option 'backup_swift_url'."))
        LOG.debug("Using swift URL %s", self.swift_url)
        self.az = CONF.storage_availability_zone
        self.data_block_size_bytes = CONF.backup_swift_object_size
        self.backup_timer_interval = CONF.backup_timer_interval
        self.data_block_num = CONF.backup_object_number_per_notification
        self.enable_progress_timer = CONF.backup_swift_enable_progress_timer
        self.swift_attempts = CONF.backup_swift_retry_attempts
        self.swift_backoff = CONF.backup_swift_retry_backoff
        self.compressor = \
            self._get_compressor(CONF.backup_compression_algorithm)
        LOG.debug('Connect to %s in "%s" mode' % (CONF.backup_swift_url,
                                                  CONF.backup_swift_auth))
        if CONF.backup_swift_auth == 'single_user':
            if CONF.backup_swift_user is None:
                LOG.error(_LE("single_user auth mode enabled, "
                              "but %(param)s not set")
                          % {'param': 'backup_swift_user'})
                raise exception.ParameterNotFound(param='backup_swift_user')
            self.conn = swift.Connection(
                authurl=CONF.backup_swift_url,
                auth_version=CONF.backup_swift_auth_version,
                tenant_name=CONF.backup_swift_tenant,
                user=CONF.backup_swift_user,
                key=CONF.backup_swift_key,
                retries=self.swift_attempts,
                starting_backoff=self.swift_backoff)
        else:
            self.conn = swift.Connection(retries=self.swift_attempts,
                                         preauthurl=self.swift_url,
                                         preauthtoken=self.context.auth_token,
                                         starting_backoff=self.swift_backoff)

    def _create_container(self, context, backup):
        backup_id = backup['id']
        container = backup['container']
        LOG.debug('_create_container started, container: %(container)s,'
                  'backup: %(backup_id)s' %
                  {'container': container, 'backup_id': backup_id})
        if container is None:
            container = CONF.backup_swift_container
            self.db.backup_update(context, backup_id, {'container': container})
        # NOTE(gfidente): accordingly to the Object Storage API reference, we
        # do not need to check if a container already exists, container PUT
        # requests are idempotent and a code of 202 (Accepted) is returned when
        # the container already existed.
        self.conn.put_container(container)
        return container

    def _generate_swift_object_name_prefix(self, backup):
        az = 'az_%s' % self.az
        backup_name = '%s_backup_%s' % (az, backup['id'])
        volume = 'volume_%s' % (backup['volume_id'])
        timestamp = timeutils.strtime(fmt="%Y%m%d%H%M%S")
        prefix = volume + '/' + timestamp + '/' + backup_name
        LOG.debug('_generate_swift_object_name_prefix: %s' % prefix)
        return prefix

    def _generate_object_names(self, backup):
        prefix = backup['service_metadata']
        swift_objects = self.conn.get_container(backup['container'],
                                                prefix=prefix,
                                                full_listing=True)[1]
        swift_object_names = [swift_obj['name'] for swift_obj in swift_objects]
        LOG.debug('generated object list: %s' % swift_object_names)
        return swift_object_names

    def _metadata_filename(self, backup):
        swift_object_name = backup['service_metadata']
        filename = '%s_metadata' % swift_object_name
        return filename

    def _write_metadata(self, backup, volume_id, container, object_list,
                        volume_meta):
        filename = self._metadata_filename(backup)
        LOG.debug('_write_metadata started, container name: %(container)s,'
                  ' metadata filename: %(filename)s' %
                  {'container': container, 'filename': filename})
        metadata = {}
        metadata['version'] = self.DRIVER_VERSION
        metadata['backup_id'] = backup['id']
        metadata['volume_id'] = volume_id
        metadata['backup_name'] = backup['display_name']
        metadata['backup_description'] = backup['display_description']
        metadata['created_at'] = str(backup['created_at'])
        metadata['objects'] = object_list
        metadata['volume_meta'] = volume_meta
        metadata_json = json.dumps(metadata, sort_keys=True, indent=2)
        reader = six.StringIO(metadata_json)
        etag = self.conn.put_object(container, filename, reader,
                                    content_length=reader.len)
        md5 = hashlib.md5(metadata_json).hexdigest()
        if etag != md5:
            err = _('error writing metadata file to swift, MD5 of metadata'
                    ' file in swift [%(etag)s] is not the same as MD5 of '
                    'metadata file sent to swift [%(md5)s]') % {'etag': etag,
                                                                'md5': md5}
            raise exception.InvalidBackup(reason=err)
        LOG.debug('_write_metadata finished')

    def _read_metadata(self, backup):
        container = backup['container']
        filename = self._metadata_filename(backup)
        LOG.debug('_read_metadata started, container name: %(container)s, '
                  'metadata filename: %(filename)s' %
                  {'container': container, 'filename': filename})
        (_resp, body) = self.conn.get_object(container, filename)
        metadata = json.loads(body)
        LOG.debug('_read_metadata finished (%s)' % metadata)
        return metadata

    def _prepare_backup(self, backup):
        """Prepare the backup process and return the backup metadata."""
        backup_id = backup['id']
        volume_id = backup['volume_id']
        volume = self.db.volume_get(self.context, volume_id)

        if volume['size'] <= 0:
            err = _('volume size %d is invalid.') % volume['size']
            raise exception.InvalidVolume(reason=err)

        try:
            container = self._create_container(self.context, backup)
        except socket.error as err:
            raise exception.SwiftConnectionFailed(reason=err)

        object_prefix = self._generate_swift_object_name_prefix(backup)
        backup['service_metadata'] = object_prefix
        self.db.backup_update(self.context, backup_id, {'service_metadata':
                                                        object_prefix})
        volume_size_bytes = volume['size'] * units.Gi
        availability_zone = self.az
        LOG.debug('starting backup of volume: %(volume_id)s to swift,'
                  ' volume size: %(volume_size_bytes)d, swift object names'
                  ' prefix %(object_prefix)s, availability zone:'
                  ' %(availability_zone)s' %
                  {
                      'volume_id': volume_id,
                      'volume_size_bytes': volume_size_bytes,
                      'object_prefix': object_prefix,
                      'availability_zone': availability_zone,
                  })
        object_meta = {'id': 1, 'list': [], 'prefix': object_prefix,
                       'volume_meta': None}
        return object_meta, container, volume_size_bytes

    def _backup_chunk(self, backup, container, data, data_offset, object_meta):
        """Backup data chunk based on the object metadata and offset."""
        object_prefix = object_meta['prefix']
        object_list = object_meta['list']
        object_id = object_meta['id']
        object_name = '%s-%05d' % (object_prefix, object_id)
        obj = {}
        obj[object_name] = {}
        obj[object_name]['offset'] = data_offset
        obj[object_name]['length'] = len(data)
        LOG.debug('reading chunk of data from volume')
        if self.compressor is not None:
            algorithm = CONF.backup_compression_algorithm.lower()
            obj[object_name]['compression'] = algorithm
            data_size_bytes = len(data)
            data = self.compressor.compress(data)
            comp_size_bytes = len(data)
            LOG.debug('compressed %(data_size_bytes)d bytes of data '
                      'to %(comp_size_bytes)d bytes using '
                      '%(algorithm)s' %
                      {
                          'data_size_bytes': data_size_bytes,
                          'comp_size_bytes': comp_size_bytes,
                          'algorithm': algorithm,
                      })
        else:
            LOG.debug('not compressing data')
            obj[object_name]['compression'] = 'none'

        reader = six.StringIO(data)
        LOG.debug('About to put_object')
        try:
            etag = self.conn.put_object(container, object_name, reader,
                                        content_length=len(data))
        except socket.error as err:
            raise exception.SwiftConnectionFailed(reason=err)
        LOG.debug('swift MD5 for %(object_name)s: %(etag)s' %
                  {'object_name': object_name, 'etag': etag, })
        md5 = hashlib.md5(data).hexdigest()
        obj[object_name]['md5'] = md5
        LOG.debug('backup MD5 for %(object_name)s: %(md5)s' %
                  {'object_name': object_name, 'md5': md5})
        if etag != md5:
            err = _('error writing object to swift, MD5 of object in '
                    'swift %(etag)s is not the same as MD5 of object sent '
                    'to swift %(md5)s') % {'etag': etag, 'md5': md5}
            raise exception.InvalidBackup(reason=err)
        object_list.append(obj)
        object_id += 1
        object_meta['list'] = object_list
        object_meta['id'] = object_id
        LOG.debug('Calling eventlet.sleep(0)')
        eventlet.sleep(0)

    def _finalize_backup(self, backup, container, object_meta):
        """Finalize the backup by updating its metadata on Swift."""
        object_list = object_meta['list']
        object_id = object_meta['id']
        volume_meta = object_meta['volume_meta']
        try:
            self._write_metadata(backup,
                                 backup['volume_id'],
                                 container,
                                 object_list,
                                 volume_meta)
        except socket.error as err:
            raise exception.SwiftConnectionFailed(reason=err)
        self.db.backup_update(self.context, backup['id'],
                              {'object_count': object_id})
        LOG.debug('backup %s finished.' % backup['id'])

    def _backup_metadata(self, backup, object_meta):
        """Backup volume metadata.

        NOTE(dosaboy): the metadata we are backing up is obtained from a
                       versioned api so we should not alter it in any way here.
                       We must also be sure that the service that will perform
                       the restore is compatible with version used.
        """
        json_meta = self.get_metadata(backup['volume_id'])
        if not json_meta:
            LOG.debug("No volume metadata to backup")
            return

        object_meta["volume_meta"] = json_meta

    def _send_progress_end(self, context, backup, object_meta):
        object_meta['backup_percent'] = 100
        volume_utils.notify_about_backup_usage(context,
                                               backup,
                                               "createprogress",
                                               extra_usage_info=
                                               object_meta)

    def _send_progress_notification(self, context, backup, object_meta,
                                    total_block_sent_num, total_volume_size):
        backup_percent = total_block_sent_num * 100 / total_volume_size
        object_meta['backup_percent'] = backup_percent
        volume_utils.notify_about_backup_usage(context,
                                               backup,
                                               "createprogress",
                                               extra_usage_info=
                                               object_meta)

    def backup(self, backup, volume_file, backup_metadata=True):
        """Backup the given volume to Swift."""
        (object_meta, container,
            volume_size_bytes) = self._prepare_backup(backup)
        counter = 0
        total_block_sent_num = 0

        # There are two mechanisms to send the progress notification.
        # 1. The notifications are periodically sent in a certain interval.
        # 2. The notifications are sent after a certain number of chunks.
        # Both of them are working simultaneously during the volume backup,
        # when swift is taken as the backup backend.
        def _notify_progress():
            self._send_progress_notification(self.context, backup,
                                             object_meta,
                                             total_block_sent_num,
                                             volume_size_bytes)
        timer = loopingcall.FixedIntervalLoopingCall(
            _notify_progress)
        if self.enable_progress_timer:
            timer.start(interval=self.backup_timer_interval)

        while True:
            data = volume_file.read(self.data_block_size_bytes)
            data_offset = volume_file.tell()
            if data == '':
                break
            self._backup_chunk(backup, container, data,
                               data_offset, object_meta)
            total_block_sent_num += self.data_block_num
            counter += 1
            if counter == self.data_block_num:
                # Send the notification to Ceilometer when the chunk
                # number reaches the data_block_num. The backup percentage
                # is put in the metadata as the extra information.
                self._send_progress_notification(self.context, backup,
                                                 object_meta,
                                                 total_block_sent_num,
                                                 volume_size_bytes)
                # reset the counter
                counter = 0

        # Stop the timer.
        timer.stop()
        # All the data have been sent, the backup_percent reaches 100.
        self._send_progress_end(self.context, backup, object_meta)

        if backup_metadata:
            try:
                self._backup_metadata(backup, object_meta)
            except Exception as err:
                with excutils.save_and_reraise_exception():
                    LOG.exception(
                        _LE("Backup volume metadata to swift failed: %s") %
                        six.text_type(err))
                    self.delete(backup)

        self._finalize_backup(backup, container, object_meta)

    def _restore_v1(self, backup, volume_id, metadata, volume_file):
        """Restore a v1 swift volume backup from swift."""
        backup_id = backup['id']
        LOG.debug('v1 swift volume backup restore of %s started', backup_id)
        container = backup['container']
        metadata_objects = metadata['objects']
        metadata_object_names = sum((obj.keys() for obj in metadata_objects),
                                    [])
        LOG.debug('metadata_object_names = %s' % metadata_object_names)
        prune_list = [self._metadata_filename(backup)]
        swift_object_names = [swift_object_name for swift_object_name in
                              self._generate_object_names(backup)
                              if swift_object_name not in prune_list]
        if sorted(swift_object_names) != sorted(metadata_object_names):
            err = _('restore_backup aborted, actual swift object list in '
                    'swift does not match object list stored in metadata')
            raise exception.InvalidBackup(reason=err)

        for metadata_object in metadata_objects:
            object_name = metadata_object.keys()[0]
            LOG.debug('restoring object from swift. backup: %(backup_id)s, '
                      'container: %(container)s, swift object name: '
                      '%(object_name)s, volume: %(volume_id)s' %
                      {
                          'backup_id': backup_id,
                          'container': container,
                          'object_name': object_name,
                          'volume_id': volume_id,
                      })
            try:
                (_resp, body) = self.conn.get_object(container, object_name)
            except socket.error as err:
                raise exception.SwiftConnectionFailed(reason=err)
            compression_algorithm = metadata_object[object_name]['compression']
            decompressor = self._get_compressor(compression_algorithm)
            if decompressor is not None:
                LOG.debug('decompressing data using %s algorithm' %
                          compression_algorithm)
                decompressed = decompressor.decompress(body)
                volume_file.write(decompressed)
            else:
                volume_file.write(body)

            # force flush every write to avoid long blocking write on close
            volume_file.flush()

            # Be tolerant to IO implementations that do not support fileno()
            try:
                fileno = volume_file.fileno()
            except IOError:
                LOG.info(_LI("volume_file does not support "
                             "fileno() so skipping"
                             "fsync()"))
            else:
                os.fsync(fileno)

            # Restoring a backup to a volume can take some time. Yield so other
            # threads can run, allowing for among other things the service
            # status to be updated
            eventlet.sleep(0)
        LOG.debug('v1 swift volume backup restore of %s finished',
                  backup_id)

    def restore(self, backup, volume_id, volume_file):
        """Restore the given volume backup from swift."""
        backup_id = backup['id']
        container = backup['container']
        object_prefix = backup['service_metadata']
        LOG.debug('starting restore of backup %(object_prefix)s from swift'
                  ' container: %(container)s, to volume %(volume_id)s, '
                  'backup: %(backup_id)s' %
                  {
                      'object_prefix': object_prefix,
                      'container': container,
                      'volume_id': volume_id,
                      'backup_id': backup_id,
                  })
        try:
            metadata = self._read_metadata(backup)
        except socket.error as err:
            raise exception.SwiftConnectionFailed(reason=err)
        metadata_version = metadata['version']
        LOG.debug('Restoring swift backup version %s', metadata_version)
        try:
            restore_func = getattr(self, self.DRIVER_VERSION_MAPPING.get(
                metadata_version))
        except TypeError:
            err = (_('No support to restore swift backup version %s')
                   % metadata_version)
            raise exception.InvalidBackup(reason=err)
        restore_func(backup, volume_id, metadata, volume_file)

        volume_meta = metadata.get('volume_meta', None)
        try:
            if volume_meta:
                self.put_metadata(volume_id, volume_meta)
            else:
                LOG.debug("No volume metadata in this backup")
        except exception.BackupMetadataUnsupportedVersion:
            msg = _("Metadata restore failed due to incompatible version")
            LOG.error(msg)
            raise exception.BackupOperationError(msg)

        LOG.debug('restore %(backup_id)s to %(volume_id)s finished.' %
                  {'backup_id': backup_id, 'volume_id': volume_id})

    def delete(self, backup):
        """Delete the given backup from swift."""
        container = backup['container']
        LOG.debug('delete started, backup: %s, container: %s, prefix: %s',
                  backup['id'], container, backup['service_metadata'])

        if container is not None:
            swift_object_names = []
            try:
                swift_object_names = self._generate_object_names(backup)
            except Exception:
                LOG.warn(_LW('swift error while listing objects, continuing'
                             ' with delete'))

            for swift_object_name in swift_object_names:
                try:
                    self.conn.delete_object(container, swift_object_name)
                except socket.error as err:
                    raise exception.SwiftConnectionFailed(reason=err)
                except Exception:
                    LOG.warn(_LW('swift error while deleting object %s, '
                                 'continuing with delete')
                             % swift_object_name)
                else:
                    LOG.debug('deleted swift object: %(swift_object_name)s'
                              ' in container: %(container)s' %
                              {
                                  'swift_object_name': swift_object_name,
                                  'container': container
                              })
                # Deleting a backup's objects from swift can take some time.
                # Yield so other threads can run
                eventlet.sleep(0)

        LOG.debug('delete %s finished' % backup['id'])

def get_backup_driver(context):
    return SwiftBackupDriver(context)


text:
RSS Twitter Facebook 15 Questions
CD, Vinyl, Mp3
home > browse > featured > interviews > article > view article
Interview with Fjordne
Tobias Fischer
Whenever a particular genre of music is considered by the public at large to be a "classic", it usually means that it has lost its ability to renew itself. After roughly five decades at the forefront of the avantgarde, over the course of which it went from its blues-infused beginnings and the commercial heydays of the swing era to the complex interactions of the free-movement and daring liaisons with atonality and contemporary composition, jazz today occasionally seems to have entered that stadium. There is still a vibrant and young scene, mind you. But its almost habitual reaction to the impending creative standstill has mainly consisted in searching for external inspiration and injecting a potent cocktail of fresh influences into its veins. Although new, border-crossing mutations and regional variations are seemingly born every few seconds, few of them have proved particularly fruitful for more than one season, with fusions like electro-jazz or jazz-influenced post-rock only serving to further the genre's branching out into myriads of sub-genres. There is nothing inherently wrong with these efforts. But to pianist and electronica-producer Shunichiro Fujimoto, the man behind projects like Starke, Braet and, most prominently, Fjordne, the real challenge has always consisted in keeping the search alive and continually pushing forward while replenishing the spirit of jazz at the source. On Charles Rendition, his first new album as Fjordne in two years, Fujimoto has considerably improved upon the machine-men interface at the heart of his previous full-length The Setting Sun and used it to put into motion a fresh concept of improvisation: Sound, rhythm and melody are all part of the equation, beneficial accidents arrive both in the act of playing and playing back and references to adjacent styles are turning into a compositional element. Imperfections are no longer an obstruction, but a natural product of this process, which doesn't have a pre-defined ending and is always cut off before it could turn predictable. In one instant, Fujimoto will dish up the most deliciously smooth and sweet harmonies, only to add timbral impurities, rhythmical asychnronicities and tonal irritations the next. It is a trademark of the entire album: Synthetic drum machines pound underneath the most lavish and deep piano textures. Field recordings pierce double bass performances taken straight out of the blue note café. And the constant polarity between the spiritual and the earthly is taken to a point where what seemed like a contradiction now merely sounds like a fascinating contrast. Charles Rendition is sure to provoke anyone who bought it blindly after the magisterial epics of The Setting Sun, and yet its business isn't provocation, but an expansion of instrumental possibilities, sonic relations and emotional impact. Fujimoto could easily have played safe on his fifth full-length as Fjordne, but opted to make use of the freedom he considers essential to come up with something that suddenly casts his entire oeuvre in a different and even more intriguing light. And isn't that just what jazz has always been about in the first place?
There's a video by one of your personal favourites Bobo Stenson, Live from the Forest, in which the musicians can be seen playing in some kind of mysterious, mist-filled woods.
I love that performance. I can really see them interacting not only with themselves but with the atmosphere. The music they're playing is genuinely "jazz". It might not be the sound that many people are used to within this particular context. But to me, it's beautiful music that I'd personally definitely define as jazz.
It's a "virtual performance", in a way and I brought it up, because you don't seem to be interested in the "live aspect" of jazz all that much.
I do listen to it on CD and records more than live performances. That is probably also why I enjoy subtle, quiet music. The reason I like jazz so much is because of the improvisation contained in it. When I started writing programs for software, I wrote them so that I could interact with them afterwards. Of course, improvisation with software is still very far from jazz performances. It's still hard to think of the computer as another player, it's mainly just an effector. This is an area many people are working on and I am looking forward to progress in the future. Having said that, the great part about jazz is not only the interaction between musicians, but the interaction between the instrument, the atmosphere and your state of mind. To do that, the music needs to be expressed spontaneously. This is something that I aim for. I would love to be able to express my music by soloing, too. But for now, I think the best way to express it is with the balance I have.
Was there perhaps a live performance, nonetheless, which left an important mark on you?
I have been to great concerts. But actually the ones that influenced me the most were the ones I found on the Internet. Thanks to youtube, I am able to see clips from the artists of the past. To name a few, I love watching the performances of Thelonious Monk, Miles Davis, and John Coltrane. The solo performances of Thelonious Monk have been particularly important, because you can really discern his use of space and harmony in them. They've influenced me a lot.
The pianists you admire – Monk, Stenson, Marc Copland and Paul Bley, among others - all arrived at strikingly different results, too.
You can add another favorite of mine to that list, Andrew Hill. The reason why I like them so much is because they have their own sound and their music is unique even though they use the same palette, which is jazz. One of the things I love about Marc Copland is that he actually moved from being a saxophonist into a pianist. He came to the conclusion that he couldn't express the music that is ringing in his head with the saxophone and switched to the piano. It's not something you could do easily. I think it helps to make him so original and unique. That is my final goal in music and I admire musicians who have reached it.
It's actually still presumptuous to call the piano my main instrument. But it is my favorite instrument and a sound that always rings in my head and a starting point when I make music. The piano is an important instrument to me but really I want to think of my music as a combination of sounds.
How do you define freedom for yourself?
I love music that extends the barrier as in genre, harmony, and rhythm. I think many people have the same way of thinking more or less. That's probably why the free jazz movement happened in the first place. I am one of those who like to push themselves to higher grounds. I feel freedom is something that you need to gain yourself. For me, I needed the skill to play the piano, and it took me a long time to get there. I still need to work on many skills to express the music I have in my head. It's something I intend to work on throughout my life.
In which way were you influenced by some of these free jazz experiments?
As the name suggests, the free jazz movement broadened the borders of jazz in terms of harmony and rhythm. I was influenced most from the point that free jazz broadened the listeners' ear of what is jazz and what isn't. It taught me how "free" you can deal with music. This is still relevant today. I believe – or at least I'd like to believe - that there is still potential for progress in most areas – one particular realm being computers. There are still many people doing interesting and beautiful things with computers and software. I would like to see how people can interact naturally with computers, not just information going in one direction - musician to computer - but in both.
This also fits in, I believe, with the importance of ECM for you – the idea that "freedom" can extend into many different realms.
There are many aspects to this question. Of course, I love the icy sounds and beautiful artwork. But the part I indeed love most is how the label broke the barrier of jazz. I think ECM built a jazz of its own by blending the native music of places in Europe with the jazz of America. And there's this trademark of ECM records, that they were and still are usually recorded within a very condensed space of time. Each of the tracks I made for Charles Rendition was made in a short time - a few days - too. I don't like spending too much time on making a track.
You did take some time off after finishing The Setting Sun to think about how and what kind of music to make.
Yes, I knew that if I started making new music, I would end up doing something that I did in the past. I know that going deeper into one direction is important. But after making the previous album, I felt that it was time to move into a new one. The albums that I have made before The Setting Sun are very close to each other in the way I approached music. I was focusing a lot more on the texture of sound than the structure of the composition. I let the music itself go in the direction it wanted to and programmed the software to do so. When I made The Setting Sun, I wanted to focus more on the structure of composition, and balance the weight put on the programs I write. After finishing the album, I felt that I have made the album that I was planning, so I didn't want to make another one like it. So to me, The Setting Sun was like the final episode of that direction in music for me.
So what were conceptual considerations for the new material?
Before I started working on Charles Rendition, I made it a rule not to use the programs I used in the past - or at least not to depend on them too much. I wanted to start making music that had a basic harmonic structure and be controlled by my performance of instruments. Just like how in jazz you have a "leadsheet" as the basic structure for improvisation. It's perhaps interesting to note in this regard that the text included in the artwork of Charles Rendition was actually written before I started making the music. I had in mind making music with an "antique" sound. I wrote the text as a guideline for the album and Charles Rendition is effectively the soundtrack to the text. It doesn't correspond to the way I think towards music, but rather represents a guideline to the color or atmosphere of sound that I wanted to express.
I knew I needed to improve my performance skills to express the music in Charles Rendition so I started practicing the piano. I had never been taught how to play the instrument in a classical way. The longest experience with instruments I have is the guitar which I haven't played in quite a while. I quit playing the guitar about two years ago to start playing the piano. Getting things to sound "organic" and "natural" was very important for this album. I wanted the music controlled and played by humans.
How did you look back on your previous efforts? Are they "incomplete" to you in a way or rather necessary steps towards achieving your highest goals?
I love moving into new directions but I don't regret the music that I have made in the past. And although I'm still far away from the music that I want to express, I think I was able to go into the right direction. Electronica was one of the influences that I had in the beginning. I love how the electro-acoustic sounds deepened the possibility of the texture of sounds. By making this kind of music myself, I was able to study how to mangle with sound. This skill was then passed on to the music production of Charles Rendition though I haven't used the same programs.
All music is incomplete in a sense. I think that's why we can relate to it in such a deep way. Especially jazz has a very beautiful "incompleteness". I think that why I am so attracted to it. I believe that my previous releases are just snapshots of the time they were made. When I look back on them, I have many parts that I want to fix. But they are what I could have achieved at that point.
By Tobias Fischer
Fjordne Discography:
Unmoving (U-Cover) 2007
Stories Apart From The World (Ryoondo-Tea) 2008
The Last 3 Days Of Time (Dynamophone) 2008
The Setting Sun (Kitchen) 2009
Charles Rendition (Kitchen) 2011
Fjordne
Tags: jazz, featured, japan, fjordne, improvisation, experimental, interviews, sound art, electronica, article
Haruka Nakamura: Twilight
A time of transition: Pure ...
With "The Setting Sun", Fjordne's ...
Fjordne: "The Setting Sun"
Nightly inspirations: Chamber music moving ...
Giuseppe Ieleasi: "(another) Stunt"
Energy and humour: The aspects ...
CD Feature/ Zeitkratzer with Carsten Nicolai, Terre Thaemlitz, Keiji Haino: "Electronics"
Music for an imperfect world: ...
CD Feature/ McCoy Tyner: "Afro Blue"
He still matters: A look ...
> Latest
> CD, Vinyl, MP3
> Concerts
> Interviews
> Countries
> Our aim
> The team
> History of Tokafi
Copyright © 2012 Tokafi. ↑ Back to top